Please Sign up or sign in to vote.

Update

I used the basis of this article in the tool you can find : https://sites.google.com/site/noiselab15/

Introduction

For some stuff I get involved concerning run time planets generation I faced procedural seamless texture generation. To create a planet at run time is foundamental to manage seamless texture. A seamless texture can work as greyscale highmap and/or landscape texture and/or atmosferic effects.

Searching the web I found some well known tecniques like perlin noise (http://en.wikipedia.org/wiki/Perlin_noise) or fractal noise.

So I decided to arrange a c# "sandbox" small project to experiment some texture generation algorithms, to test performance , and so on. In particular I implemented a Perlin noise generator using resources from web (references will follow), after that I've created some recoursive algoritms that can reach, in my opinon, sadisfactory effects compared to Perlin, at a good performance cost. Here I'm going to share some stuff.

Background

I implemented Perlin noise studing these web sources : http://www.sepcot.com/blog/2006/08/PDN-PerlinNoise2d and http://freespace.virgin.net/hugo.elias/models/m_perlin.htm . I'm not going to explain Perlin noise , first reason I'm not so smart to explain something I merely understand better than the links above.

Another (this time easy) thing usefull before going ahead is to know what a grayscale image is and how usefull it is for define a heightmap. At the same time is usefull to know how to use the alpha chanell of an image , for example to add clouds on a predefined sky.

The basic idea is to draw on a random sub region of the image a light grey rectangle (let's call it a "box") covering the sub region. After that we calculate n random point near the center of first box , we reduce box size (i.e by half) and we repeat for the n small boxes. Every time we draw a box we add its grey delta to the preexistents pixels.

In the sequence below we start with 2 recursion calls and we end with 20 recursion call. For the last image we repeat it 7 times and we reduce the grey delta to make vanishing the bigger boxes.

Finaly, the textures created are seamless and perfectly tileable

Using the code

The main recursive method of Contoli noise is very simple :

private void printQuad( float [,] Values, int wid, int hei, int x, int y, int boxSize, int deepness, int delta) { if (deepness > 0 && boxSize>= 1 ) { for ( int i = -boxSize/2; i < boxSize/2; i++) { for ( int j = -boxSize / 2 ; j < boxSize / 2 ; j++) { int pixX = (x + i) % wid; int pixY = (y + j) % hei; if (pixX < 0 ) pixX = wid + pixX; if (pixY < 0 ) pixY = wid + pixY; Values[pixX, pixY] = Values[pixX, pixY] + delta; Iterations++; } int xx = r.Next(x, x + boxSize); int yy = r.Next(y, y + boxSize); printQuad(Values, wid, hei, xx, yy, boxSize / 2 , --deepness, delta); } } }

Where:

Values is the bidimensional array of float representing the image pixels

wid and hei are the image dimension

x and y are the center point coords of the box

boxSize is the size of the rectangle

deepness how deep in recursion are now

delta how many grey scale we add over existing values. (It represent the delta height)

Stopping the recursion :

if (deepness > 0 && boxSize>= 1 )

we stop the recursion if we are too deep or if box size reachs zero.

To call it ;

r = getrRandom(); //r is public Random class accessed by all methods for (int nr = 0; nr < N_Repetitions; nr++) { //get a random point int x = r.Next(0, wid - 1); int y = r.Next(0, hei - 1); printQuad(Values, wid, hei, x, y, box_size, Godeep, d); } updBitmap(Values, tmp, grayScale.Checked); pictureBox1.Image = tmp; pictureBox1.Refresh();

updBitmap converts the Values array in a greyscaled bitmap.

getRandom initialize the random number generator used inside printQuad .

N_Repetitions is self explained.

The application:

The Contoli Noise Methods:

Quad : the simplest already discussed;

Circ : draws circles instead of rectangles, we get a better effect keeping recursion deepness low;

Func ; draws a 2 variable function instead of rectangles. Actualy the function is a Torus ( http://en.wikipedia.org/wiki/Torus) .

Quad (left) VS Circ (right):

The torus example: 1 recursion deepnes vs 33 recursion deepnes.

General note: when incrementing "recursion" value is good to decrement "delta color" value.

Using the printFunc code.

//TORUS f func = (x1,y1) => (float)Math.Sqrt((0.4f * 0.4f - Math.Pow((0.6f - Math.Sqrt(x1 * x1 + y1 * y1)), 2)));//TORUS printFunc(Values, wid, hei, x, y, box_size, Godeep, d,func); useValueArray = true; break;

printFunc accepts a function f delegate. If you don't like TORUS You can redefine it the way you want.

Example for paraboloid:

f func = (x1,y1) => 1f + (float) ((x1*x1)/1f + (y1*y1)/1f) * -1f; //PARABOLOID

In the "Distance alg." section I present a set of algorithms to generate effects over a bitmap using tecniques based on distances from a set of random points. It's work in progress.

Voronoi diagram

In the Voronoi section we can experiment some implementations of the procedural space tesselation, based on Voronoi idea. The basic idea is : 1) take a random set S of points on a plane; 2) every point "s" of S defines a region "r" on the plane where each point in the region "r" is the closest to point "s" (harder to explain tha understand) 3) use some random color (grayscale) to paint each region (or the region borders) 4) add some coding to keep all the stuff "seamless"

The examples:

The code:

private void Voronoi( float [,] Values, int wid, int hei, int [,] points) { for ( int i = 0 ; i < wid; i++) { for ( int j = 0 ; j < hei; j++) { float minDist = Math.Min(wid,hei); int minV = 0 ; for ( int p = 0 ; p < points.GetLength( 0 ); p++) { int pX = points[p, 0 ]; int pY = points[p, 1 ]; int pV = points[p, 2 ]; Double Dist1X = Math.Abs((i - pX)); Double Dist1Y = Math.Abs((j - pY)); Double Dist2X = wid - Dist1X; Double Dist2Y = hei - Dist1Y; Dist1X = Math.Min(Dist1X, Dist2X); Dist1Y = Math.Min(Dist1Y, Dist2Y); float dist = ( float )Math.Sqrt(Math.Pow(Dist1X, 2 ) + Math.Pow(Dist1Y, 2 )); if (dist < minDist) { minDist = dist; minV = pV; } } Values[i, j] = minV; Iterations++; } } }

3D Noise

Going 3d. I added a 3d implementation of contoli noise and voronoi noise. To test it simply push "Start 3d noise" , wait some time depending on the parameters , enjoy.

Some explanation , in this case the 3rd dimension is TIME, so we get an "animated" noise. If you comapare printQuad3D with printQuad you'll find the 3rd dimension management. Obviosly, even the 3rd dimension is seamless, and let the animation to loop without cuts.

Animation demo links:

Quad 3d noise:

https://www.youtube.com/watch?v=cVnhmmPVSf8

Circ 3d noise:

https://www.youtube.com/watch?v=cFVYq_cS5C4

https://www.youtube.com/watch?v=7qPrKBut6qY

Voronoi animations

https://www.youtube.com/watch?v=GnR6dLPxvNc

https://www.youtube.com/watch?v=uihClJuwqz8

https://www.youtube.com/watch?v=TpkrNQe4guQ

https://www.youtube.com/watch?v=CfpY8saDa9U

History

First version.

9-NOV-2014 : added VORONOI section.

12-NOV-2014 : added 3D Noise section.

14-NOV-2014 : added 3d noise demos youtube links