Noise functions, saves to image

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Quinnx
Posts: 9
Joined: Thu Dec 16, 2010 4:17 am

Noise functions, saves to image

Post by Quinnx »

I looked long and hard for noise code, but I couldn't find anything that I could get to work with irrlicht easily. So I looked around at papers and other code shared freely and spent a long time coming up with code to generate my own noise code. I finally did it a while ago..and since it was so hard, I thought I'd share this with everyone as well as I'm new to these forums.

If you look at the code, I put in several "levels" of color (for height obviously) if you set the noise to be colored. This way you can create a very simple version of a diffuse map for the same greyscale noise for a heightmap. You could add more levels, change the color, use noise functions on the color its self, etc. The result of combing a greyscale image, and the same image only colored, then with a detail material with a noisy sand-like texture for detail looks great on a terrain in game.

Give it at least 10 seconds to display something when you run the program, it will take time with the default settings.

The parameters you can mess with in the main code without screwing anything are grouped just under int main().
NoiseSize - the image size. Keep it the same size as the window size..or smaller.
NoiseZoom - This determines how close you are to the noise, the higher you set this the smaller the noise shapes will be.
Octaves - This acts kinda like my color technique in the header file, the higher, the more detail, 5 is too high to be honest. The higher, expect longer times to generate the noise, because it's going to be going over the same code that many more times per pixel = long time.
Persistence - Like NoiseZoom, but much more leathal. Keep this a double number in most cases other wise you'll end up with images like you get when you don't have a signal on older tvs.
Colored - Self explanatory. Grey-scale, or not. 0 = grey-scale.


If I had a site to upload pics to display here I'd upload a few results.

Now, this is only rough code, the parameters may be hard to understand and the like. If you have questions about the code, ask.

Here it is:

This is a header file.

Code: Select all

#include "iostream"
#include "math.h"
#include "irrlicht.h"

using namespace std;
using namespace irr;
using namespace core;
using namespace io;
using namespace video;
using namespace scene;

namespace Noise
{

	inline double FindNoise(int seed, double x,double y);
	inline double Interpolate(double a,double b,double x);
	ITexture* Render_Clouds(int seed, bool colored,int w,int h,double zoom,int oct,double p,int r,int g,int b,IVideoDriver* driver);
	int Live(int seed, bool colored,int w,int h,double zoom, int octaves ,double p, int r, int g, int b,IVideoDriver* driver);
	double SmoothNoise(int seed, double x,double y);
	double InterpolateNoise(int seed, double x, double y);
	double DNoise(double x);
};

inline double Noise::DNoise(double x)
{                        
	int n = (int(x)<<13) ^ int(x);

	//return (double)( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & Ox7fffffff) / 1073741824.0); 
	int nn=(n*(n*n*60493+19990303)+1376312589)&0x7fffffff;
	return 1.0-((double)nn/1073741824.0);
};


inline double Noise::FindNoise(int seed, double x,double y)
{
	int n=(int)x+(int)y*57;
	n=(n<<13)^n;
	int nn=(n*(n*n*seed+19990303*seed)+1376312589)&0x7fffffff;
	return 1.0-((double)nn/1073741824.0);
};

inline double Noise::Interpolate(double a,double b,double x)
{
	double ft = x * 3.1415927;
	double f = (1.0-cos(ft)) * 0.5;
	return a * (1.0-f) + b * f;
};

double Noise::SmoothNoise(int seed, double x,double y)
{
	int smooth = 1;
	int cr =  16;
	int si = 8;
	int cn = 4;
	double corners = ( FindNoise(seed, x-smooth, y-smooth)+FindNoise(seed, x+smooth, y-smooth)+FindNoise(seed, x-smooth, y+smooth)+FindNoise(seed, x+smooth, y+smooth) ) / cr;
    double sides   = ( FindNoise(seed, x-smooth, y) +FindNoise(seed, x+smooth, y) +FindNoise(seed, x, y-smooth) +FindNoise(seed, x, y+smooth) ) / si;
    double center  =  FindNoise(seed, x, y) / cn;

    return corners + sides + center;
};

double Noise::InterpolateNoise(int seed, double x, double y)
{
	double integer_X    = int(x);
    double fractional_X = x - integer_X;

    double integer_Y    = int(y);
    double fractional_Y = y - integer_Y;

    double v1 = SmoothNoise(seed, integer_X,     integer_Y);
    double v2 = SmoothNoise(seed, integer_X + 1, integer_Y);
    double v3 = SmoothNoise(seed, integer_X,     integer_Y + 1);
    double v4 = SmoothNoise(seed, integer_X + 1, integer_Y + 1);

    double i1 = Interpolate(v1 , v2 , fractional_X);
    double i2 = Interpolate(v3 , v4 , fractional_X);

    return Interpolate(i1 , i2 , fractional_Y);
};

int r, g, b;

ITexture* Noise::Render_Clouds(int seed, bool colored,int w,int h,double zoom, int octaves ,double p, int r, int g, int b,IVideoDriver* driver)
{

	double total = 0;//FindNoise(rand(),rand());
	ITexture* File = 0;
	bool water = false;

	IImage* NoiseMap =
		driver->createImage(ECF_R8G8B8,dimension2d<u32>(h,w));
	u8 * ff=(u8 *)NoiseMap->lock();

	for(int y=0;y<h;y++)
	{
		for(int x=0;x<w;x++)
		{
			total = 0;

			for(int a=0;a<octaves-1;a++)//This loops trough the octaves.
			{
				double frequency = pow(2.0,a);//This increases the frequency with every loop of the octave.
				double amplitude = pow(p,a);//This decreases the amplitude with every loop of the octave.

				total = total + InterpolateNoise(seed, x * frequency / zoom, y / zoom * frequency) * amplitude;
			}
			
			if (colored == 1)
			{
				bool water = false;

				int height = (int)((total*128.0)+128.0);//Convert to 0-256 values.
				if (height<=0)
				{
					height=0;
					water = true;

					r = 0;
					g = 150;
					b = 195;
				}
				if (height>=50)
				{
					water = true;

					r = 0;
					g = 155;
					b = 200;
				}
				if (height>=145)
				{
					r = 232;
					g = 223;
					b = 230;
				}
				if (height>=150)
				{
					r = 114;
					g = 193;
					b = 101;
				}
				if (height>=200)
				{
					r = 201;
					g = 193;
					b = 101;
				}
				if (height>=250)
				{
					r = 217;
					g = 227;
					b = 237;
				}
				if (height>=255)
				{
					height=255;

					r = 227;
					g = 237;
					b = 247;
				}

				double random = DNoise(int(rand()));

				if (random >= .25)
				{
					//if (water == false)
					//{
						int smooth = (int)((random)*2+total);

						r = r + smooth;
						g = g + smooth;
						b = b + smooth;
					//}
				}

				if (random >= .50)
				{
					//if (water == false)
					//{
						int smooth = (int)((random)*5+total);

						r = r + smooth;
						g = g + smooth;
						b = b + smooth;
					//}
				}

				NoiseMap->
					setPixel(x,y,SColor(255,(int)r,(int)g,(int)b),false);
			}
			else
			{
				int height = (int)((total*128.0)+128.0);//Convert to 0-256 values.
				if(height>255)
					height=255;
				if(height<0)
					height=0;

				NoiseMap->
					setPixel(x,y,SColor(255,(int)height,(int)height,(int)height),false);
			}
		}
	}

	if (NoiseMap)
	{
		cout << "Image created.\n";
	}
	else
	{
		cout << "Image failed.\n";
	}

	bool i =
		driver->writeImageToFile(NoiseMap,"NoiseMaps/noise.bmp",0);
	//NoiseMap->drop();
	//Tex->drop();

	if (i)
	{
		cout << "Image exported.\n";
		ITexture* File =
			driver->getTexture("NoiseMaps/noise.bmp");
	}
	else
	{
		cout << "Image failed to export.\n";
	}

	return File;
};
and the main:

Code: Select all

#include "Noise.h"

using namespace std;
using namespace irr;
using namespace core;
using namespace io;
using namespace video;
using namespace scene;

#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif

//------------------------------------------------------------------------------------------------
// Default device settings
//------------------------------------------------------------------------------------------------
E_DRIVER_TYPE driverType = EDT_DIRECT3D9;
int deviceWidth = 512;
int deviceHeight = deviceWidth;
int bits = 32;
int AA = 0; // AntiAliasing off default
bool AnisotropicFilter = false;
bool StencilBuffer = false; // Shadows
bool windowMode = false; // false = windowed
bool vsync = false;
SIrrlichtCreationParameters Parameters;

int main()
{
	int NoiseSize = 512;
	int NoiseZoom = 40;
	int Octaves = 5;
	double Persistance = .60;
	bool Colored = 0;

        int SeedNumber = 60493;

	cout << "Seed Number: ";
	cin >> SeedNumber;

	Parameters.AntiAlias = AA;
	Parameters.DriverType = driverType;
	Parameters.Bits = bits;
	Parameters.Vsync = vsync;
	Parameters.Fullscreen = windowMode;
	Parameters.WindowSize.Width = deviceWidth;
	Parameters.WindowSize.Height = deviceHeight;

	IrrlichtDevice* device =
		createDeviceEx(Parameters);
	if (device == 0)
		return 1;

	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();

	driver->setTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY, true);
	driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);


	Noise::Render_Clouds(SeedNumber,Colored,NoiseSize,NoiseSize,NoiseZoom,Octaves,Persistance, 0, 0, 0,driver);
	ITexture* Map =
		driver->getTexture("NoiseMaps/noise.bmp");


	int lastFPS = -1;

	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, SColor(255,200,150,150));
		smgr->drawAll();

		driver->draw2DImage(Map,vector2d<s32>(0,0)); // display noise image

		driver->endScene();

		int fps = driver->getFPS();
		if (lastFPS != fps)
		{
			stringw str = L"Endless Engine [";
			str += driver->getName();
			str += "] FPS:";
			str += fps;

			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
	 }
	device->drop();
	
	return 0;
}
Enjoy. Let me know how you like it...and how it works for you.
Last edited by Quinnx on Wed Dec 29, 2010 4:54 am, edited 3 times in total.
drarem
Posts: 81
Joined: Mon Mar 06, 2006 4:40 am
Contact:

Post by drarem »

Nice and slick. I realized I had to create a NoiseMaps directory first and this is info on using Linux and opengl. It took about half a second to pull up the noise map and FPS at default windowed screen resolution averaged 565. This is on an AMD quad core phenom with onboard video card nvidia 8200, ubuntu 10.10 and no compiz pretty effects. I didn't have tchar.h in my path but found it compiled fine without it.
Quinnx
Posts: 9
Joined: Thu Dec 16, 2010 4:17 am

Post by Quinnx »

drarem wrote:Nice and slick. I realized I had to create a NoiseMaps directory first and this is info on using Linux and opengl. It took about half a second to pull up the noise map and FPS at default windowed screen resolution averaged 565. This is on an AMD quad core phenom with onboard video card nvidia 8200, ubuntu 10.10 and no compiz pretty effects. I didn't have tchar.h in my path but found it compiled fine without it.
Oh, yeah. My system specs are kinda way outdated. (building new pc atm with that amd six core phenom II ) :lol:
I get a result in a couple seconds....I'm on an intel Pentium D dual core at 2.36ghz each, for now. My graphics card is out dated too... VisionTek radeon x1300 xge with 512mb.
Glad it worked well for you. half a second is starting to sound pretty useful!
You shouldn't need either stdio.h or tchar.h. I don't use them...I just didn't delete them from when I started the project from VS 08.
yaten
Posts: 41
Joined: Tue Nov 16, 2010 4:57 pm
Location: /home/yaten on a server somewhere East of Asia
Contact:

Post by yaten »

Great program sir quinnx, thanks for sharing ^_^
I just wonder, when I try to run the program, the output is always the same even if I delete the generated file noise.bmp, is that intentional or I am doing something wrong? ^_^
Quinnx
Posts: 9
Joined: Thu Dec 16, 2010 4:17 am

Post by Quinnx »

yaten wrote:Great program sir quinnx, thanks for sharing ^_^
I just wonder, when I try to run the program, the output is always the same even if I delete the generated file noise.bmp, is that intentional or I am doing something wrong? ^_^
Thank you!

The thing with changing the output, you need to change the "seed number."

To do that go to the header file and look at this function:

Code: Select all

inline double Noise::FindNoise(double x,double y)
{
   int n=(int)x+(int)y*57;
   n=(n<<13)^n;
   int nn=(n*(n*n*60493+19990303)+1376312589)&0x7fffffff;
   return 1.0-((double)nn/1073741824.0);
}; 

the int "nn"change the numbers, add more n*'s that will change the output. thought I thought it's supposed to be a certain type of number for it to work...I think any will. For example replace "60493" with 19990303 the same as the one next to it......Huge difference.

I should add some code where the user can input their own seed number.
Quinnx
Posts: 9
Joined: Thu Dec 16, 2010 4:17 am

Update

Post by Quinnx »

Updated the code..
You can now input your own seed number via the consul for different results. Put the same number in you'll get the same result every time.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Post by Granyte »

nice job you did on that one through your reading have you found anything regarding 3d noise?
anoki
Posts: 58
Joined: Fri May 05, 2006 8:31 am

Post by anoki »

Looks nice,

do you have a screenshot ?
Dareltibus
Posts: 115
Joined: Mon May 17, 2010 7:42 am

Post by Dareltibus »

it is a bit slow but the speed seems only 5-10% slower than libnoise. good job.
Quinnx
Posts: 9
Joined: Thu Dec 16, 2010 4:17 am

Post by Quinnx »

Granyte wrote:nice job you did on that one through your reading have you found anything regarding 3d noise?
Yes I did, and I also did with 3d noise.....but I decided to not even try to do that. The techniques to do that are completely different. You can't do it with a 2d image. You have to store it as data....then have something that can read that data like voxels or something. I don't quite understand how to use Irrlicht to store something as raw data....other wise I'd take a shot at that too. I'm very interested in it. That's actually what I set out to do..but ran into that wall.

How ever, it's about the same idea as "generating" 2d noise to generate 3d noise. There's multiple ways...but the idea is that there's just another dimension you add. The 2d image from a 2d noise...creates 3d height meshes. unless you're just using it as a texture. Then a 3d noise is basically a 4d mesh. There's height, width, depth, then something I call "in or out". If it's done right, you can create ultra realistic terrains with it.

I read Nivida's GPU Gems 3 on doing this. What they do is store the "noise data" in a giant table. Then have a voxel system look at the table....etc..

Here's a link: http://http.developer.nvidia.com/GPUGem ... _ch01.html

So it's def. possible to do.[/url]
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Post by Granyte »

well the idea would be to use it to generate a height map that would be wraped around a spherical terrain idealy i'd use voxel to to have arch cavern and stuf but it seem just overly complicated for a starting project

and especialy as the only reason 3d noise is neded in a such case is because a flat 2d map simply won,t accept to be wraped around a sphere (unless some one know some incredible glitch to do so)



but if voxels are needed polyvox or other voxel library could be used?

i started try tp use polyvox and sofar ....... documentation is LACKING
Quinnx
Posts: 9
Joined: Thu Dec 16, 2010 4:17 am

Re: Noise functions, saves to image

Post by Quinnx »

I've been silently working on on 3d noise. I've got a formula that creates a result with caverns. I render it with individual cubes so I can visualize it. It looks just like minecraft untextured.

Also have started the main project that will be using the code. It's a huge project that I cannot disclose any other info on atm.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Noise functions, saves to image

Post by Granyte »

well over time i got to write my own version of 3d noise mine run on shaders and is used to generate planets proceduraly on the fly i guess it could be used to generate cavern arch over and under pass but i have no way to render this in my current implementation
Quinnx
Posts: 9
Joined: Thu Dec 16, 2010 4:17 am

Re: Noise functions, saves to image

Post by Quinnx »

Youre on the right track with voxels. http://http.developer.nvidia.com/GPUGem ... _ch01.html They explain how it works here.
This way it doesn't have to be rendered with cubes like minecraft is. It's smooth terrain. Of course much harder to work out as it's no longer a flat sphere.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Noise functions, saves to image

Post by Granyte »

ya but thier technique require geometry shaders wich are not yet availible in dx for irrlicht so i would end up using polyvox and generating the mesh on the cpu with would be blody slow for a dynamic lod like the one i use so ill probably have a look at this again when ill integrate polyvox for the asteorids or something like it .
Post Reply