Click here to Skip to main content
15,883,705 members
Articles / Programming Languages / C#

Procedural seamless noise texture generator

Rate me:
Please Sign up or sign in to vote.
4.98/5 (39 votes)
3 Feb 2015CPOL4 min read 67.1K   1.8K   50   6
Presentation and testing of some procedural bitmap creation algorithms .

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 :

C#
//
// CONTOLI NOISE

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++)
                    {
                            /*seamless management start*/
                            int pixX = (x + i) % wid;
                            int pixY = (y + j) % hei;
                            if (pixX < 0)
                                pixX = wid + pixX;
                            if (pixY < 0)
                                pixY = wid + pixY;
                            /*seamless management end*/

                            Values[pixX, pixY] = Values[pixX, pixY] + delta; // add value

                            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

and 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 : 

C#
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:

C#
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]; //0..255
                Double Dist1X = Math.Abs((i - pX));
                Double Dist1Y = Math.Abs((j - pY));
                Double Dist2X = wid - Dist1X;
                Double Dist2Y = hei - Dist1Y;
                /*to grant seamless I take the min between distX and wid-distX
                 |                       |
                 |                       |     ----------- = Dist1X
                 |...i-----------X.......|     ..........  = Dist2X
                 |                       |
                 */
                Dist1X = Math.Min(Dist1X, Dist2X);
                /*to grant seamless I take the min between distY and hei-distY*/
                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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Italy Italy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionBitmap output Pin
Member 1446187324-May-19 4:06
Member 1446187324-May-19 4:06 
QuestionStarfield generator Pin
Ihor Salnikov6-Apr-15 4:15
Ihor Salnikov6-Apr-15 4:15 
AnswerRe: Starfield generator Pin
andrea contoli6-Apr-15 6:54
andrea contoli6-Apr-15 6:54 
GeneralRe: Starfield generator Pin
Ihor Salnikov6-Apr-15 7:08
Ihor Salnikov6-Apr-15 7:08 
QuestionMy vote of 5! Pin
Volynsky Alex12-Nov-14 4:04
professionalVolynsky Alex12-Nov-14 4:04 
GeneralMy vote of 5 Pin
Stylianos Polychroniadis11-Nov-14 11:00
Stylianos Polychroniadis11-Nov-14 11:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.