Perlin Noise gives too small values?

Started by
2 comments, last by Dev_NightDreamer 9 years, 8 months ago

Hello.

Today I've implemented a perlin noise algorithm with extra methods like pertubation and eroding to create a terrain. smile.png

I found the code for it here: Click me smile.png

After the "addPerlinNoise()" method, you can see 3 reference pictures on that page (in the middle), build with the frequencies 1.0f, 4.0f and 1.0f + 8.0f (without perturb or sth like that, just plain noise).

If I use a frequency of 4.0f, this is my output (plain noise): https://imgur.com/7OElD3n

And when I use 64.0f as my frequency, I get this: https://imgur.com/dqA04N6

Can you help me to achieve something like the reference pictures with the reference frequencies (1.0f, 4.0f, 1.0f + 8.0f)?

I only understand a little behind the maths of it, so I can't really do something to fix it. sad.png

The code on the linked site is in C#, mine is in C++.

The only things, which are different between my code and the code on the site is the following part:


void PerlinGenerator::initGradients()
{
	//Type of random number distribution
	std::uniform_real_distribution<float> dist(0.0f, 1.0f);  //(min, max)

	//Mersenne Twister: Good quality random number generator
	std::mt19937 rng;
	//Initialize with non-deterministic seeds
	rng.seed(std::random_device{}());

	for (int i = 0; i < gradientTableSize; i++)
	{
		float z = 1.0f - 2.0f * dist(rng);
		float r = (float)sqrt(1.0f - z * z);
		float theta = 2 * (float)M_PI * dist(rng);
		gradients[i * 3] = r * cos(theta);
		gradients[i * 3 + 1] = r * sin(theta);
		gradients[i * 3 + 2] = z;
	}
}

Can it be the random double, which is used for the computing?

For the rendering I determine the vertex coordinates for a VBO like this and render it with glDrawElements(...) :


void Terrain::createVBO()
{
	// Create vertex data
	float *vertices = new float[3 * heightMap->size * heightMap->size];
	float blockSize = 16.0f;
	int vertex = 0;

	for (int y = 0; y < heightMap->size; y++) {
		for (int x = 0; x < heightMap->size; x++) {
			vertices[vertex++] = x * blockSize;
			vertices[vertex++] = y * blockSize;
			vertices[vertex++] = heightMap->heights[y][x] * blockSize;
		}
	}

	// Create index data
	[...]

	// Create VAO
	[...]

	// Create VBO
	[...]

	// Create EBO
	[...]

	// Handle vertex attributes in shader prog
	[...]
}

Hopefully you can help me, thanks,

NightDreamer

Advertisement

I found some ugly things in your link: http://www.float4x4.net/index.php/2010/06/generating-realistic-and-playable-terrain-height-maps/

  1. This is 3D perlin noise. However heightmaps should use 2D noise. Using 3D noise with heightmaps is useless, at the end you will be discarding one coordinate: Heights[i, j] += Perlin.Noise(f * i / (float)Size, f * j / (float)Size, 0); Watch that zero, the third coordinate is useless. Using 3D perlin noise can work, but 2D noise is easier and cheaper(in terms of performance).
  2. The smooth function use the old 3p² - 2p³. However this is not C2 (it is C1), it should be 6p^5-15p^4+10p^3 (http://mrl.nyu.edu/~perlin/paper445.pdf)
  3. The implementation uses a permutation table. This is a performance optimization. However for a 2D noise generator I will use a simple gradient table, without permutations.
  4. I think that the way InitGradients initialize the gradients is complex and performance expensive. Try this:

Rng rng=new rng(-1,1);//Random numbers on [-1,1] interval
vec3 g=(rng.next(),rng.next(),rng.next());
g=normalize(g);

I prefer this Perlin noise reference: http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html I think that this link is very comprehensible.

About your particular problem:

  • Your second picture looks good. Noise won't be noticeable if the frecuency is too high compared to the vertex density (vertex/triangles per unit²).
  • Even though your second picture looks good you may want more abrupt terrain. Try increasing the amplitude:

public void AddPerlinNoise(float f, float amplitude)
{
      for (int i = 0; i < Size; i++)
      {
           for (int j = 0; j < Size; j++)
           {
                  Heights[i, j] += amplitude*Perlin.Noise(f * i / (float)Size, f * j / (float)Size, 0);
           }
      }
}


Developer of Raiseland, a real-time procedural terrain generator. Check out our Greenlight: http://steamcommunity.com/sharedfiles/filedetails/?id=280019434

Thank you very much for replying. wink.png

This is 3D perlin noise. However heightmaps should use 2D noise. Using 3D noise with heightmaps is useless, at the end you will be discarding one coordinate: Heights[i, j] += Perlin.Noise(f * i / (float)Size, f * j / (float)Size, 0); Watch that zero, the third coordinate is useless. Using 3D perlin noise can work, but 2D noise is easier and cheaper(in terms of performance).

Alright, I think I will implement 2D noise. smile.png

The smooth function use the old 3p² - 2p³. However this is not C2 (it is C1), it should be 6p^5-15p^4+10p^3 (http://mrl.nyu.edu/~perlin/paper445.pdf)

I don't know, what you mean by "C2 (it is C1)". Would you explain that to me? rolleyes.gif

I prefer this Perlin noise reference: http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html I think that this link is very comprehensible.

Thank you very much. I'll have a look at it and try it out. biggrin.png

I don't know, what you mean by "C2 (it is C1)". Would you explain that to me? rolleyes.gif
C0 = points are connected, no holes (basically a polyline)

C1 = tangents (the "first derivative") interpolate smoothly (e.g. a typica cubic spline)

C2 = tangents interpolate smoothly and curvature (the "second derivtative") is smooth, too.

In particular, in this case it means that the second derivative is zero both for t = 0 and t = 1. The difference between C1 and C2 appears to be not so important, after all, the curve is "smooth" either way. However, it becomes grossly visible once you do something like e.g. bump mapping. C1 will give you nasty artifacts.

Ah, okay, thank you very much! smile.png
Due to the word "derivative" I now know what you meant.
Just didn't know, that you can name it as C0/C1/... wink.png
In university, we only use "derivative"... rolleyes.gif

This topic is closed to new replies.

Advertisement