using perlin noise to generate terrain height??

Started by
9 comments, last by rjpr 19 years, 8 months ago
Hi, after reading and making same search about perlin noise i have some doubts. First of all, i want to generate different terrain 256x256pixels using perlin noise, giving me results from 0 to 255. one of the this that i dont understand in every page i read is the perlin_noise2D function receive the number of octaves, the frequency and a X and Y point wich should be different from int, but to generate a complete terrain wich values should i send??? can anyone give me an example please?? another thing is that some use permutation tables and an array with random numbers wich should be always the same and in others they generate the number by giving the x and y?? wich is better? regards for all replys
YeTi
Advertisement
I assume that the X and Y values are the coordinates of the point where you are computing the height. To build a heightmap using this kind of function, you must run through all points in your map, and for each of them, get the height by calling the function with the X and Y coordinates of that point.

For each Point[X][Y] in Map do  Point[X][Y].Height = Perlin(X,Y,Constants)


However, if you intend to store the heights in a map anyway, and intend to code the perlin function yourself, I suggest you adapt the algorithm to your needs by generating the terrain octave after octave in layers.
clicky
this is where i learnt how to do perlin noise, which i know use for my cloud generation, heighmap generation and my terrain textuing. i spose i might as well bung in my CTextureGenerator class, as theres no original code in there.

// TextureGenerator.cpp: implementation of the CTextureGenerator class.////////////////////////////////////////////////////////////////////////#include <math.h>#include "TextureGenerator.h"//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CTextureGenerator::CTextureGenerator(){	m_p1=15731;	m_p2=789221;	m_p3=1376312589;	m_freq=0.01f;	m_per= 0.55f;}CTextureGenerator::~CTextureGenerator(){}float CTextureGenerator::Interpolate(float x, float y, float a) {//dunnofloat fac1 = float(3*pow(1-a, 2) - 2*pow(1-a,3));float fac2 = float(3*pow(a, 2) - 2*pow(a, 3));return x*fac1 + y*fac2; //add the weighted factors//linearreturn  x*(1.0f-a) + y*a;//cosinefloat ft = a * 3.1415927f;float f = (1.0f - (float)cos(ft)) * 0.5f;return  x*(1-f) + y*f;}float CTextureGenerator::SmoothedNoise(int x, int y){	float ret = 0.0f;	float corners = ( Random(x-1, y-1)+Random(x+1, y-1)+Random(x-1, y+1)+Random(x+1, y+1) ) / 16;	float sides   = ( Random(x-1, y)  +Random(x+1, y)  +Random(x, y-1)  +Random(x, y+1) ) /  8;	float center  =  Random(x, y) / 4;	ret = corners + sides + center;	return ret;}float CTextureGenerator::GetValue(float x, float y) {     int Xint = (int)x;     int Yint = (int)y;     float Xfrac = x - Xint;     float Yfrac = y - Yint;     float x0y0 = Random(Xint, Yint);  //find the noise values of the four corners     float x1y0 = Random(Xint+1, Yint);     float x0y1 = Random(Xint, Yint+1);     float x1y1 = Random(Xint+1, Yint+1);     //interpolate between those values according to the x and y fractions     float v1 = Interpolate(x0y0, x1y0, Xfrac); //interpolate in x direction (y)     float v2 = Interpolate(x0y1, x1y1, Xfrac); //interpolate in x direction (y+1)     float fin = Interpolate(v1, v2, Yfrac);  //interpolate in y direction     return fin;}float CTextureGenerator::Noise(int x, int y){	float total = 0;    float amplitude = 1;    float freq_factor = m_freq;    for(int k=0; k<6; k++) 	{        total += GetValue(x*freq_factor, y*freq_factor) * amplitude;        amplitude *= m_per;        freq_factor *= 2;     }	total += 1.0f;	total /= 2.0f;//	total = total*0.5f + 0.5f;    if(total<0.0f) total = 0.0f;    if(total>1) total = 1.0f;	return total;//    int fin = (int)(total*255.0f); //get in color range//    Color col = Color.FromArgb(fin, fin, fin);//  bmp.SetPixel(j, i, col);}void CTextureGenerator::UpdateRow(int sizex, int sizey, float *data, int row, int newRow){	for (int i=0;i<sizex;i++)		{//			Random(i,j,&m_grads[(j*ysize)+i]);			data[(row*sizey)+i] = Noise(i,newRow);		}}void CTextureGenerator::UpdateCol(int sizex, int sizey, float *data, int col, int newCol){	for (int i=0;i<sizex;i++)		{//			Random(i,j,&m_grads[(j*ysize)+i]);			data[(i*sizey)+col] = Noise(newCol,i);		}}BOOL CTextureGenerator::Generate(int xsize,int ysize, float *data){	for (int j=0;j<ysize;j++)	for (int i=0;i<xsize;i++)		{//			Random(i,j,&m_grads[(j*ysize)+i]);			data[(j*ysize)+i] = Noise(i,j);		}	return TRUE;}float CTextureGenerator::Random(int x, int y){   int n;   n = x + y * 57;   n = (n<<13) ^ n;   int temp = ( (n * (n * ((n * m_p1) + m_p2)) + m_p3) & 0x7fffffff );   float f = (float)temp;   float res = (float)( 1.0 -(f / 1073741824.0f));   return res;}void CTextureGenerator::Seed(int p1, int p2, int p3, float freq,float per){	m_p1=p1;	m_p2=p2;	m_p3=p3;	m_freq=freq;	m_per= per;}


all you need to do to create a grid of floats (in the range [0,1]) is
	#define SIZE 256	float *data = new float[SIZE*SIZE];	CTextureGenerator texGen;	srand(GetTickCount());	texGen.Seed(rand(),rand(),rand(),0.006f,0.55f);	texGen.Generate(SIZE,SIZE,data);	// do whatever	delete[data];


hope this helps
i is 1337
i think im making stupid questions, i already read all that pages and see the code, but still have 2 questions.

first i want to draw a simple image using perlin noise, like those seen in the pages with grey color only (0-255).

to do it for example to a 256x256 image i want to make:

for each point(x,y) ,
color value is perlinNoise2d(x,y,octaves,frequency)

my doubt is, i read that x and y could not be int, wich values sould i send if i want for example color the coord(1,1)??

and other thing is to know if im making the alghoritm correct, for it i saw this page : http://www.angelcode.com/dev/perlin/perlin.asp

and the gradient use permutation table, can i simple use the function random wich return the same value with the same input as post here before??
YeTi
SoDdit : can you tell me wich interval support m_freq and m_per???

tks
YeTi
>>my doubt is, i read that x and y could not be int, wich values sould i send if i want for example color the coord(1,1)??<<

devide the ints by a higher value
eg instead of sending 1 (devide it by say 234 first)
float(1) / 234.0
The NVidia CG toolkit 1.1 contains a fully hardware accellerated version of terrain generation using perlin noise, take a look at it, maybe it isn't really usefull to you but it's speed is really amazing.
Quote:Original post by rjpr
SoDdit : can you tell me wich interval support m_freq and m_per???

m_freq is the frequency of the noise map, the higher it is the close to pure white noise it will be.
m_per is the persistance of the data, ie how much the higher octaves of noise affect the final output.

these are set by the Seed method, as demonstrated in the second source block.
i is 1337
SodDit: i understand that, the only thing i want to know is wich values can be the input like m_per is [0;1] or what are the real values, like random function produce values between [-1;1] i want to know the interval of this..
YeTi
well techically the values of m_per and m_freq can be anything you want them to be, however going too far one way or the other will make the resultant heightmap either flat (too low on m_freq) or pure white noise (too high)
your best bet is to make a test app that just has a dialog with edit controls for both m_per and m_freq (and you might as well do the other three ints as well) and creates a little 256x256 image that you then display on the dialog. if you put in an "update image" button on there you can play with the values until you get something you like then leave the m_freq and m_per alone and play with the three ints. any new map with just the ints varied should have a similar effect.
i is 1337

This topic is closed to new replies.

Advertisement