private float sample( Vector3 pos, PlanetNoise noiseParams, PlanetNoisePerlin perlinNoise )
		{
			float result	= 0f;
			float offset	= 0f;

			if( noiseParams.smearOctaves > 0 )
			{
				offset = perlinNoise.getOctave( pos / noiseParams.smearScale, noiseParams.smearOctaves );
				offset = Mathf.Pow( offset, noiseParams.smearFalloff );
				offset *= noiseParams.smearIntensity;
			}

			result = perlinNoise.getNormalisedOctave( ( pos / noiseParams.scale ) + ( Vector3.one * offset ), noiseParams.octaves );

			if( noiseParams.ridginess > 0f )
			{
				float ridge	= perlinNoise.getNormalisedOctave( ( pos / noiseParams.scale ) + new Vector3( offset, offset, offset + 11f ), noiseParams.octaves );
				result		= ( noiseParams.ridginess * ( 1f - ( Mathf.Abs( ridge - 0.5f ) * 2f ) ) ) + ( ( 1f - noiseParams.ridginess ) * result );
			}

			result = Mathf.Pow( result, noiseParams.falloff );
			result = Mathf.Clamp01( result * noiseParams.intensity );

			return result;
		}
Example #2
0
        private bool showGUINoise(PlanetNoise planetNoise, string name, bool show)
        {
            EditorGUILayout.BeginHorizontal();
            {
                show = EditorGUILayout.Foldout(show, name);

                if (GUILayout.Button("Randomise", EditorStyles.miniButton))
                {
                    Undo.RecordObject(_target, "Randomise " + name);
                    _target.randomiseNoise(planetNoise);
                    EditorApplication.delayCall += updatePreviewIfAvailable;
                }
            }
            EditorGUILayout.EndHorizontal();

            ++EditorGUI.indentLevel;

            if (show)
            {
                planetNoise.scale          = showGUISlider("scale", planetNoise.scale, 0.1f, 20f);
                planetNoise.octaves        = showGUISlider("octaves", planetNoise.octaves, 0, 10);
                planetNoise.falloff        = showGUISlider("falloff", planetNoise.falloff, 0f, 20f);
                planetNoise.intensity      = showGUISlider("intensity", planetNoise.intensity, 0f, 20f);
                planetNoise.ridginess      = showGUISlider("rigidness", planetNoise.ridginess, 0f, 1f);
                planetNoise.smearScale     = showGUISlider("smearScale", planetNoise.smearScale, 0.1f, 20f);
                planetNoise.smearOctaves   = showGUISlider("smearOctaves", planetNoise.smearOctaves, 0, 10);
                planetNoise.smearFalloff   = showGUISlider("smearFalloff", planetNoise.smearFalloff, 0f, 20f);
                planetNoise.smearIntensity = showGUISlider("smearIntensity", planetNoise.smearIntensity, 0f, 20f);
            }

            --EditorGUI.indentLevel;

            return(show);
        }
 public void randomiseNoise(PlanetNoise noise)
 {
     noise.scale          = Random.Range(0.1f, 20f);
     noise.octaves        = Random.Range(0, 10);
     noise.falloff        = Random.Range(0f, 20f);
     noise.intensity      = Random.Range(0f, 20f);
     noise.ridginess      = Random.Range(0f, 1f);
     noise.smearScale     = Random.Range(0.1f, 20f);
     noise.smearOctaves   = Random.Range(0, 10);
     noise.smearFalloff   = Random.Range(0f, 20f);
     noise.smearIntensity = Random.Range(0f, 20f);
 }
		public void generateDiffuseNoise( int width, int height,
											PlanetNoise surfaceParams,
											PlanetNoise landParams,
											Color[] landColour,
											PlanetNoise[] landColourNoise,
											float cityReach,
											float cityHeight,
											Color waterColour0,
											Color waterColour1,
											float waterLevel,
											float waterSpecular,
											float waterFalloff,
											Color iceColour,
											float iceReach,
											float iceHeight,
											float shadowRange,
											float shadowStrength,
											float normalScale )
		{
			_width				= width;
			_height				= height;
			_surfaceParams		= surfaceParams;
			_landParams			= landParams;
			_landColour			= landColour;
			_landColourNoise	= landColourNoise;
			_cityReach			= cityReach * 0.5f;
			_cityHeight			= cityHeight;
			_waterColour0		= waterColour0;
			_waterColour1		= waterColour1;
			_waterLevel			= waterLevel;
			_waterSpecular		= waterSpecular;
			_waterFalloff		= waterFalloff;
			_iceColour			= iceColour;
			_iceReach			= iceReach * 0.5f;
			_iceHeight			= iceHeight;
			_shadowRange		= shadowRange;
			_shadowStrength		= shadowStrength;
			_normalScale		= normalScale;
			
			//9 bytes per pixel - all colour data followed by all normal data followed by all illumination data
			//colour - r, g, b, a
			//normal - x, y, z, height
			//illumination - i
			int bytesPerPixel	= 9;
			int pixelCount		= width * height;

			if( diffuseData == null || diffuseData.Length != pixelCount * bytesPerPixel )
				diffuseData = new byte[ pixelCount * bytesPerPixel ];
			
			if( useComputerShader )
			{
				noiseComputeShader.SetFloat( "width",	width );
				noiseComputeShader.SetFloat( "height",	height );

				//diffuse perlin noise data
				int gradBytes		= sizeof( float );
				int gradStride		= PlanetNoisePerlin.gradStride;
				float[] gradArray	= new float[ gradStride * 4 ];

				System.Buffer.BlockCopy( perlinNoiseSurface.getGradArray(),			0, gradArray, 0,							gradStride * gradBytes );
				System.Buffer.BlockCopy( perlinNoiseLand.getGradArray(),			0, gradArray, gradStride * gradBytes,		gradStride * gradBytes );
				System.Buffer.BlockCopy( perlinNoiseLandColour01.getGradArray(),	0, gradArray, gradStride * gradBytes * 2,	gradStride * gradBytes );
				System.Buffer.BlockCopy( perlinNoiseLandColour23.getGradArray(),	0, gradArray, gradStride * gradBytes * 3,	gradStride * gradBytes );

				perlinGradBuffer = new ComputeBuffer( gradArray.Length, gradBytes );
				perlinGradBuffer.SetData( gradArray );
				noiseComputeShader.SetBuffer( _diffuseKernel, "perlinGrad", perlinGradBuffer );

				int permBytes		= sizeof( int );
				int permStride		= PlanetNoisePerlin.permStride;
				uint[] permArray	= new uint[ permStride * 4 ];

				System.Buffer.BlockCopy( perlinNoiseSurface.getPermArray(),			0, permArray, 0,							permStride * permBytes );
				System.Buffer.BlockCopy( perlinNoiseLand.getPermArray(),			0, permArray, permStride * permBytes,		permStride * permBytes );
				System.Buffer.BlockCopy( perlinNoiseLandColour01.getPermArray(),	0, permArray, permStride * permBytes * 2,	permStride * permBytes );
				System.Buffer.BlockCopy( perlinNoiseLandColour23.getPermArray(),	0, permArray, permStride * permBytes * 3,	permStride * permBytes );

				perlinPermBuffer = new ComputeBuffer( permArray.Length, permBytes );
				perlinPermBuffer.SetData( permArray );
				noiseComputeShader.SetBuffer( _diffuseKernel, "perlinPerm", perlinPermBuffer );

				//surface noise data
				noiseComputeShader.SetFloat( "surfaceScale",			surfaceParams.scale );
				noiseComputeShader.SetInt( "surfaceOctaves",			surfaceParams.octaves );
				noiseComputeShader.SetFloat( "surfaceFalloff",			surfaceParams.falloff );
				noiseComputeShader.SetFloat( "surfaceIntensity",		surfaceParams.intensity );
				noiseComputeShader.SetFloat( "surfaceRidginess",		surfaceParams.ridginess );
				noiseComputeShader.SetFloat( "surfaceSmearScale",		surfaceParams.smearScale );
				noiseComputeShader.SetInt( "surfaceSmearOctaves",		surfaceParams.smearOctaves );
				noiseComputeShader.SetFloat( "surfaceSmearFalloff",		surfaceParams.smearFalloff );
				noiseComputeShader.SetFloat( "surfaceSmearIntensity",	surfaceParams.smearIntensity );

				//land noise data
				noiseComputeShader.SetFloat( "landScale",			landParams.scale );
				noiseComputeShader.SetInt( "landOctaves",			landParams.octaves );
				noiseComputeShader.SetFloat( "landFalloff",			landParams.falloff );
				noiseComputeShader.SetFloat( "landIntensity",		landParams.intensity );
				noiseComputeShader.SetFloat( "landRidginess",		landParams.ridginess );
				noiseComputeShader.SetFloat( "landSmearScale",		landParams.smearScale );
				noiseComputeShader.SetInt( "landSmearOctaves",		landParams.smearOctaves );
				noiseComputeShader.SetFloat( "landSmearFalloff",	landParams.smearFalloff );
				noiseComputeShader.SetFloat( "landSmearIntensity",	landParams.smearIntensity );

				//land colours
				for( int i = 0; i < landColour.Length; ++i )
					noiseComputeShader.SetFloats( "landColour" + i, new float[] { landColour[ i ].r, landColour[ i ].g, landColour[ i ].b, landColour[ i ].a } );

				for( int i = 0; i < landColourNoise.Length; ++i )
				{
					string id = ( i * 2 ).ToString() + ( i * 2 + 1 ).ToString();

					//land colour noise data
					noiseComputeShader.SetFloat( "landColour" + id + "Scale",			landColourNoise[ i ].scale );
					noiseComputeShader.SetInt( "landColour" + id + "Octaves",			landColourNoise[ i ].octaves );
					noiseComputeShader.SetFloat( "landColour" + id + "Falloff",			landColourNoise[ i ].falloff );
					noiseComputeShader.SetFloat( "landColour" + id + "Intensity",		landColourNoise[ i ].intensity );
					noiseComputeShader.SetFloat( "landColour" + id + "Ridginess",		landColourNoise[ i ].ridginess );
					noiseComputeShader.SetFloat( "landColour" + id + "SmearScale",		landColourNoise[ i ].smearScale );
					noiseComputeShader.SetInt( "landColour" + id + "SmearOctaves",		landColourNoise[ i ].smearOctaves );
					noiseComputeShader.SetFloat( "landColour" + id + "SmearFalloff",	landColourNoise[ i ].smearFalloff );
					noiseComputeShader.SetFloat( "landColour" + id + "SmearIntensity",	landColourNoise[ i ].smearIntensity );
				}

				//diffuse params
				noiseComputeShader.SetFloat( "cityReach",		_cityReach );
				noiseComputeShader.SetFloat( "cityHeight",		cityHeight );
				noiseComputeShader.SetFloats( "waterColour0",	new float[] { waterColour0.r, waterColour0.g, waterColour0.b, waterColour0.a } );
				noiseComputeShader.SetFloats( "waterColour1",	new float[] { waterColour1.r, waterColour1.g, waterColour1.b, waterColour1.a } );
				noiseComputeShader.SetFloat( "waterLevel",		waterLevel );
				noiseComputeShader.SetFloat( "waterSpecular",	waterSpecular );
				noiseComputeShader.SetFloat( "waterFalloff",	waterFalloff );
				noiseComputeShader.SetFloats( "iceColour",		new float[] { iceColour.r, iceColour.g, iceColour.b, iceColour.a } );
				noiseComputeShader.SetFloat( "iceReach",		_iceReach );
				noiseComputeShader.SetFloat( "iceHeight",		iceHeight );
				noiseComputeShader.SetFloat( "shadowRange",		shadowRange );
				noiseComputeShader.SetFloat( "shadowStrength",	shadowStrength );
				noiseComputeShader.SetFloat( "normalScale",		normalScale );
				
				int pixelsPerDispatch = pixelCount;

				if( pixelsPerDispatch > maxThreadsPerDispatch )
				{
					pixelsPerDispatch = maxThreadsPerDispatch;
					pixelsPerDispatch -= maxThreadsPerDispatch % diffuseThreadsPerGroup;
				}

				noiseComputeShader.SetInt( "threadOffset", 0 );

				_jobCount			= Mathf.CeilToInt( pixelCount / ( float ) pixelsPerDispatch );
				_jobStartedCount	= 1;	//first dispatch is below
				_jobCompletedCount	= 0;

				computeResultBuffer = new ComputeBuffer( pixelsPerDispatch * diffusePixelsPerThread, sizeof( int ) );
				noiseComputeShader.SetBuffer( _diffuseKernel, "resultData", computeResultBuffer );

				noiseComputeShader.Dispatch( _diffuseKernel, pixelsPerDispatch / diffuseThreadsPerGroup, 1, 1 );

				computeResultData = new int[ pixelsPerDispatch * diffusePixelsPerThread ];
			}
			else
			{
				int workerCount = SystemInfo.processorCount - 1;				//-1 to account for main thread

				if( workerCount > 0 )
					_worker = new Thread[ workerCount ];

				//a bit inefficient to have more jobs than workers but with multiple threads
				//per core nowadays it makes sense, also gives an easy way to measure progress
				_jobCount			= Mathf.Max( 32, ( workerCount + 1 ) * ( workerCount + 1 ) );
				_jobCount			= Mathf.Min( width, _jobCount );
				_jobStartedCount	= 0;
				_jobCompletedCount	= 0;
				_jobList			= new int[ _jobCount ];

				for( int i = 0; i < _jobCount; ++i )
					_jobList[ i ] = i;

				for( int i = 0; i < workerCount; ++i )
				{
					_worker[ i ] = new Thread( () => { while( doDiffuseWork() ); } );
					_worker[ i ].Start();
				}
			}
		}
		public void generateCloudNoise( int width, int height,
										PlanetNoise cloudParams,
										int cloudWorleyNoiseOctaves,
										float cloudWorleyNoiseFrequency,
										float cloudWorleyNoiseAmplitude,
										float cloudShadowRange,
										float cloudShadowStrength,
										Color cloudColour0,
										Color cloudColour1,
										float cloudSpin,
										float cloudNormalScale,
										bool preMultiplyAlpha )
		{
			_width						= width;
			_height						= height;
			_cloudWorleyNoiseOctaves	= cloudWorleyNoiseOctaves;
			_cloudWorleyNoiseFrequency	= cloudWorleyNoiseFrequency;
			_cloudWorleyNoiseAmplitude	= cloudWorleyNoiseAmplitude;
			_cloudShadowRange			= cloudShadowRange;
			_cloudShadowStrength		= cloudShadowStrength;
			_cloudParams				= cloudParams;
			_cloudColour0				= cloudColour0;
			_cloudColour1				= cloudColour1;
			_cloudSpin					= cloudSpin;
			_cloudNormalScale			= cloudNormalScale;
			_preMultiplyAlpha			= preMultiplyAlpha;

			//8 bytes per pixel - all colour data followed by all normal data
			//colour - r, g, b, a
			//normal - x, y, z, height
			int bytesPerPixel	= 8;
			int pixelCount		= width * height;

			if( cloudData == null || cloudData.Length != pixelCount * bytesPerPixel )
				cloudData = new byte[ pixelCount * bytesPerPixel ];

			if( useComputerShader )
			{
				noiseComputeShader.SetFloat( "width",	width );
				noiseComputeShader.SetFloat( "height",	height );

				//perlin noise data
				float[] gradArray	= perlinNoiseCloud.getGradArray();
				perlinGradBuffer	= new ComputeBuffer( gradArray.Length, sizeof( float ) );
				perlinGradBuffer.SetData( gradArray );
				noiseComputeShader.SetBuffer( _cloudKernel, "perlinGrad", perlinGradBuffer );

				uint[] permArray	= perlinNoiseCloud.getPermArray();
				perlinPermBuffer	= new ComputeBuffer( permArray.Length, sizeof( int ) );
				perlinPermBuffer.SetData( permArray );
				noiseComputeShader.SetBuffer( _cloudKernel, "perlinPerm", perlinPermBuffer );

				noiseComputeShader.SetInt( "cloudSeed", worleyNoiseCloud.seed );

				//cloud noise data
				noiseComputeShader.SetFloat( "cloudScale",			cloudParams.scale );
				noiseComputeShader.SetInt( "cloudOctaves",			cloudParams.octaves );
				noiseComputeShader.SetFloat( "cloudFalloff",		cloudParams.falloff );
				noiseComputeShader.SetFloat( "cloudIntensity",		cloudParams.intensity );
				noiseComputeShader.SetFloat( "cloudRidginess",		cloudParams.ridginess );
				noiseComputeShader.SetFloat( "cloudSmearScale",		cloudParams.smearScale );
				noiseComputeShader.SetInt( "cloudSmearOctaves",		cloudParams.smearOctaves );
				noiseComputeShader.SetFloat( "cloudSmearFalloff",	cloudParams.smearFalloff );
				noiseComputeShader.SetFloat( "cloudSmearIntensity",	cloudParams.smearIntensity );

				//cloud worley noise data
				noiseComputeShader.SetInt( "cloudWorleyNoiseOctaves",		_cloudWorleyNoiseOctaves );
				noiseComputeShader.SetFloat( "cloudWorleyNoiseFrequency",	_cloudWorleyNoiseFrequency );
				noiseComputeShader.SetFloat( "cloudWorleyNoiseAmplitude",	_cloudWorleyNoiseAmplitude );

				noiseComputeShader.SetFloat( "cloudShadowRange",	_cloudShadowRange );
				noiseComputeShader.SetFloat( "cloudShadowStrength",	_cloudShadowStrength );

				//cloud params
				noiseComputeShader.SetFloats( "cloudColour0",		new float[] { cloudColour0.r, cloudColour0.g, cloudColour0.b, cloudColour0.a } );
				noiseComputeShader.SetFloats( "cloudColour1",		new float[] { cloudColour1.r, cloudColour1.g, cloudColour1.b, cloudColour1.a } );
				noiseComputeShader.SetFloat( "cloudSpin",			cloudSpin );
				noiseComputeShader.SetFloat( "cloudNormalScale",	cloudNormalScale );
				noiseComputeShader.SetInt( "preMultiplyAlpha",		preMultiplyAlpha ? 1 : 0 );
				
				int pixelsPerDispatch = pixelCount;

				if( pixelsPerDispatch > maxThreadsPerDispatch )
				{
					pixelsPerDispatch = maxThreadsPerDispatch;
					pixelsPerDispatch -= maxThreadsPerDispatch % cloudThreadsPerGroup;
				}

				noiseComputeShader.SetInt( "threadOffset", 0 );

				_jobCount			= Mathf.CeilToInt( pixelCount / ( float ) pixelsPerDispatch );
				_jobStartedCount	= 1;	//first dispatch is below
				_jobCompletedCount	= 0;

				computeResultBuffer = new ComputeBuffer( pixelsPerDispatch * cloudPixelsPerThread, sizeof( int ) );
				noiseComputeShader.SetBuffer( _cloudKernel, "resultData", computeResultBuffer );

				noiseComputeShader.Dispatch( _cloudKernel, pixelsPerDispatch / cloudThreadsPerGroup, 1, 1 );

				computeResultData = new int[ pixelsPerDispatch * cloudPixelsPerThread ];
			}
			else
			{
				int workerCount = SystemInfo.processorCount - 1;				//-1 to account for main thread

				if( workerCount > 0 )
					_worker = new Thread[ workerCount ];

				//a bit inefficient to have more jobs than workers but with multiple threads
				//per core nowadays it makes sense, also gives an easy way to measure progress
				_jobCount			= Mathf.Max( 32, ( workerCount + 1 ) * ( workerCount + 1 ) );
				_jobCount			= Mathf.Min( width, _jobCount );
				_jobStartedCount	= 0;
				_jobCompletedCount	= 0;
				_jobList			= new int[ _jobCount ];

				for( int i = 0; i < _jobCount; ++i )
					_jobList[ i ] = i;

				for( int i = 0; i < workerCount; ++i )
				{
					_worker[ i ] = new Thread( () => { while( doCloudWork() ); } );
					_worker[ i ].Start();
				}
			}
		}
		private float sample( Vector3 pos, PlanetNoise noiseParams, PlanetNoisePerlin perlinNoise )
		{
			float result	= 0f;
			float offset	= 0f;

			if( noiseParams.smearOctaves > 0 )
			{
				offset = perlinNoise.getOctave( pos / noiseParams.smearScale, noiseParams.smearOctaves );
				offset = Mathf.Pow( offset, noiseParams.smearFalloff );
				offset *= noiseParams.smearIntensity;
			}

			result = perlinNoise.getNormalisedOctave( ( pos / noiseParams.scale ) + ( Vector3.one * offset ), noiseParams.octaves );

			if( noiseParams.ridginess > 0f )
			{
				float ridge	= perlinNoise.getNormalisedOctave( ( pos / noiseParams.scale ) + new Vector3( offset, offset, offset + 11f ), noiseParams.octaves );
				result		= ( noiseParams.ridginess * ( 1f - ( Mathf.Abs( ridge - 0.5f ) * 2f ) ) ) + ( ( 1f - noiseParams.ridginess ) * result );
			}

			result = Mathf.Pow( result, noiseParams.falloff );
			result = Mathf.Clamp01( result * noiseParams.intensity );

			return result;
		}
		private Color getSurfaceColour( Vector3 pos, PlanetNoise noiseParams, Color colour0, Color colour1, PlanetNoisePerlin perlinNoise )
		{
			float c			= sample( pos, noiseParams, perlinNoise );
			Color result	= Color.Lerp( colour0, colour1, 1f - c );
			return result;
		}
		private float getSurfaceHeight( Vector3 pos, PlanetNoise noiseParams, PlanetNoisePerlin perlinNoise )
		{
			float result = sample( pos, noiseParams, perlinNoise );
			return result;
		}
        public void OnEnable()
        {
            if (surfaceNoise == null)
            {
                surfaceNoise      = new PlanetNoise();
                landNoise         = new PlanetNoise();
                landColourNoise01 = new PlanetNoise();
                landColourNoise23 = new PlanetNoise();
                cloudNoise        = new PlanetNoise();


                seedSurface      = Random.Range(0, int.MaxValue);
                seedLand         = Random.Range(0, int.MaxValue);
                seedLandColour01 = Random.Range(0, int.MaxValue);
                seedLandColour23 = Random.Range(0, int.MaxValue);
                seedCity         = Random.Range(0, int.MaxValue);
                seedCloud        = Random.Range(0, int.MaxValue);


                surfaceNoise.scale          = 0.9f;
                surfaceNoise.octaves        = 10;
                surfaceNoise.falloff        = 4.94f;
                surfaceNoise.intensity      = 2.75f;
                surfaceNoise.ridginess      = 0.46f;
                surfaceNoise.smearScale     = 0.6f;
                surfaceNoise.smearOctaves   = 1;
                surfaceNoise.smearFalloff   = 7.9f;
                surfaceNoise.smearIntensity = 0.8f;


                landNoise.scale          = 0.68f;
                landNoise.octaves        = 1;
                landNoise.falloff        = 3.74f;
                landNoise.intensity      = 3.09f;
                landNoise.ridginess      = 0f;
                landNoise.smearScale     = 2f;
                landNoise.smearOctaves   = 1;
                landNoise.smearFalloff   = 1.04f;
                landNoise.smearIntensity = 1.61f;

                landColour0 = new Color(152f / 255f, 107f / 255f, 71f / 255f);
                landColour1 = new Color(69f / 255f, 43f / 255f, 22f / 255f);
                landColour2 = new Color(0f / 255f, 20f / 255f, 0f / 255f);
                landColour3 = new Color(11f / 255f, 64f / 255f, 11f / 255f);

                landColourNoise01.scale          = 0.49f;
                landColourNoise01.octaves        = 9;
                landColourNoise01.falloff        = 9.13f;
                landColourNoise01.intensity      = 16.16f;
                landColourNoise01.ridginess      = 0.234f;
                landColourNoise01.smearScale     = 19.76f;
                landColourNoise01.smearOctaves   = 1;
                landColourNoise01.smearFalloff   = 9.53f;
                landColourNoise01.smearIntensity = 15.73f;

                landColourNoise23.scale          = 0.49f;
                landColourNoise23.octaves        = 9;
                landColourNoise23.falloff        = 9.13f;
                landColourNoise23.intensity      = 16.16f;
                landColourNoise23.ridginess      = 0.234f;
                landColourNoise23.smearScale     = 19.76f;
                landColourNoise23.smearOctaves   = 1;
                landColourNoise23.smearFalloff   = 9.53f;
                landColourNoise23.smearIntensity = 15.73f;


                waterColour0  = new Color(3f / 255f, 3f / 255f, 52f / 255f);
                waterColour1  = new Color(0f / 255f, 0f / 255f, 88f / 255f);
                waterLevel    = 0.5f;
                waterSpecular = 1f;
                waterFalloff  = 3.1f;


                iceColour = new Color(1f, 1f, 234f / 255f, 1f);
                iceReach  = 0.308f;
                iceHeight = 0.986f;


                shadowRange    = 20f;
                shadowStrength = 0.4f;


                cityReach        = 0.8f;
                cityHeight       = 0.8f;
                cityColour       = new Color(37f / 255f, 27f / 255f, 17f / 255f);
                cityCount        = 128;
                cityMultiplier   = 6;
                cityDropoff      = 4;
                cityDepth        = 4;
                citySpread       = 0.45f;
                cityIntensity    = 64f;
                maxCityIntensity = 7.5f;
                cityFalloff      = 0.5f;


                normalScale = 0.1f;


                cloudNoise.scale          = 0.4f;
                cloudNoise.octaves        = 10;
                cloudNoise.falloff        = 4.1f;
                cloudNoise.intensity      = 6.1f;
                cloudNoise.ridginess      = 0f;
                cloudNoise.smearScale     = 16.38f;
                cloudNoise.smearOctaves   = 3;
                cloudNoise.smearFalloff   = 4.2f;
                cloudNoise.smearIntensity = 5.15f;

                cloudWorleyNoiseOctaves   = 1;
                cloudWorleyNoiseFrequency = 6f;
                cloudWorleyNoiseAmplitude = 0.5f;

                cloudShadowRange    = 10f;
                cloudShadowStrength = 0.1f;

                cloudColour0 = new Color(1f, 1f, 1f, 1f);
                cloudColour1 = new Color(0f, 0f, 0f, 0f);

                cloudSpin        = 1f;
                cloudNormalScale = 0.01f;


                size = 0;
                combineHeightWithCity = true;
            }
        }
		private bool showGUINoise( PlanetNoise planetNoise, string name, bool show )
		{
			EditorGUILayout.BeginHorizontal();
			{
				show = EditorGUILayout.Foldout( show, name );

				if( GUILayout.Button( "Randomise", EditorStyles.miniButton ) )
				{
					Undo.RecordObject( _target, "Randomise " + name );
					_target.randomiseNoise( planetNoise );
					EditorApplication.delayCall += updatePreviewIfAvailable;
				}
			}
			EditorGUILayout.EndHorizontal();

			++EditorGUI.indentLevel;
			
			if( show )
			{
				planetNoise.scale			= showGUISlider( "scale",			planetNoise.scale,			0.1f,	20f );
				planetNoise.octaves			= showGUISlider( "octaves",			planetNoise.octaves,		0,		10 );
				planetNoise.falloff			= showGUISlider( "falloff",			planetNoise.falloff,		0f,		20f );
				planetNoise.intensity		= showGUISlider( "intensity",		planetNoise.intensity,		0f,		20f );
				planetNoise.ridginess		= showGUISlider( "rigidness",		planetNoise.ridginess,		0f,		1f );
				planetNoise.smearScale		= showGUISlider( "smearScale",		planetNoise.smearScale,		0.1f,	20f );
				planetNoise.smearOctaves	= showGUISlider( "smearOctaves",	planetNoise.smearOctaves,	0,		10 );
				planetNoise.smearFalloff	= showGUISlider( "smearFalloff",	planetNoise.smearFalloff,	0f,		20f );
				planetNoise.smearIntensity	= showGUISlider( "smearIntensity",	planetNoise.smearIntensity,	0f,		20f );
			}
			
			--EditorGUI.indentLevel;
			
			return show;
		}
		public void generateDiffuseNoise( int width, int height,
											PlanetNoise surfaceParams,
											PlanetNoise landParams,
											Color[] landColour,
											PlanetNoise[] landColourNoise,
											float cityReach,
											float cityHeight,
											Color waterColour0,
											Color waterColour1,
											float waterLevel,
											float waterSpecular,
											float waterFalloff,
											Color iceColour,
											float iceReach,
											float iceHeight,
											float shadowRange,
											float shadowStrength,
											float normalScale )
		{
			_width				= width;
			_height				= height;
			_surfaceParams		= surfaceParams;
			_landParams			= landParams;
			_landColour			= landColour;
			_landColourNoise	= landColourNoise;
			_cityReach			= cityReach * 0.5f;
			_cityHeight			= cityHeight;
			_waterColour0		= waterColour0;
			_waterColour1		= waterColour1;
			_waterLevel			= waterLevel;
			_waterSpecular		= waterSpecular;
			_waterFalloff		= waterFalloff;
			_iceColour			= iceColour;
			_iceReach			= iceReach * 0.5f;
			_iceHeight			= iceHeight;
			_shadowRange		= shadowRange;
			_shadowStrength		= shadowStrength;
			_normalScale		= normalScale;
			
			//9 bytes per pixel - all colour data followed by all normal data followed by all illumination data
			//colour - r, g, b, a
			//normal - x, y, z, height
			//illumination - i
			int bytesPerPixel	= 9;
			int pixelCount		= width * height;

			if( diffuseData == null || diffuseData.Length != pixelCount * bytesPerPixel )
				diffuseData = new byte[ pixelCount * bytesPerPixel ];
			
			if( useComputerShader )
			{
				noiseComputeShader.SetFloat( "width",	width );
				noiseComputeShader.SetFloat( "height",	height );

				//diffuse perlin noise data
				int gradBytes		= sizeof( float );
				int gradStride		= PlanetNoisePerlin.gradStride;
				float[] gradArray	= new float[ gradStride * 4 ];

				System.Buffer.BlockCopy( perlinNoiseSurface.getGradArray(),			0, gradArray, 0,							gradStride * gradBytes );
				System.Buffer.BlockCopy( perlinNoiseLand.getGradArray(),			0, gradArray, gradStride * gradBytes,		gradStride * gradBytes );
				System.Buffer.BlockCopy( perlinNoiseLandColour01.getGradArray(),	0, gradArray, gradStride * gradBytes * 2,	gradStride * gradBytes );
				System.Buffer.BlockCopy( perlinNoiseLandColour23.getGradArray(),	0, gradArray, gradStride * gradBytes * 3,	gradStride * gradBytes );

				perlinGradBuffer = new ComputeBuffer( gradArray.Length, gradBytes );
				perlinGradBuffer.SetData( gradArray );
				noiseComputeShader.SetBuffer( _diffuseKernel, "perlinGrad", perlinGradBuffer );

				int permBytes		= sizeof( int );
				int permStride		= PlanetNoisePerlin.permStride;
				uint[] permArray	= new uint[ permStride * 4 ];

				System.Buffer.BlockCopy( perlinNoiseSurface.getPermArray(),			0, permArray, 0,							permStride * permBytes );
				System.Buffer.BlockCopy( perlinNoiseLand.getPermArray(),			0, permArray, permStride * permBytes,		permStride * permBytes );
				System.Buffer.BlockCopy( perlinNoiseLandColour01.getPermArray(),	0, permArray, permStride * permBytes * 2,	permStride * permBytes );
				System.Buffer.BlockCopy( perlinNoiseLandColour23.getPermArray(),	0, permArray, permStride * permBytes * 3,	permStride * permBytes );

				perlinPermBuffer = new ComputeBuffer( permArray.Length, permBytes );
				perlinPermBuffer.SetData( permArray );
				noiseComputeShader.SetBuffer( _diffuseKernel, "perlinPerm", perlinPermBuffer );

				//surface noise data
				noiseComputeShader.SetFloat( "surfaceScale",			surfaceParams.scale );
				noiseComputeShader.SetInt( "surfaceOctaves",			surfaceParams.octaves );
				noiseComputeShader.SetFloat( "surfaceFalloff",			surfaceParams.falloff );
				noiseComputeShader.SetFloat( "surfaceIntensity",		surfaceParams.intensity );
				noiseComputeShader.SetFloat( "surfaceRidginess",		surfaceParams.ridginess );
				noiseComputeShader.SetFloat( "surfaceSmearScale",		surfaceParams.smearScale );
				noiseComputeShader.SetInt( "surfaceSmearOctaves",		surfaceParams.smearOctaves );
				noiseComputeShader.SetFloat( "surfaceSmearFalloff",		surfaceParams.smearFalloff );
				noiseComputeShader.SetFloat( "surfaceSmearIntensity",	surfaceParams.smearIntensity );

				//land noise data
				noiseComputeShader.SetFloat( "landScale",			landParams.scale );
				noiseComputeShader.SetInt( "landOctaves",			landParams.octaves );
				noiseComputeShader.SetFloat( "landFalloff",			landParams.falloff );
				noiseComputeShader.SetFloat( "landIntensity",		landParams.intensity );
				noiseComputeShader.SetFloat( "landRidginess",		landParams.ridginess );
				noiseComputeShader.SetFloat( "landSmearScale",		landParams.smearScale );
				noiseComputeShader.SetInt( "landSmearOctaves",		landParams.smearOctaves );
				noiseComputeShader.SetFloat( "landSmearFalloff",	landParams.smearFalloff );
				noiseComputeShader.SetFloat( "landSmearIntensity",	landParams.smearIntensity );

				//land colours
				for( int i = 0; i < landColour.Length; ++i )
					noiseComputeShader.SetFloats( "landColour" + i, new float[] { landColour[ i ].r, landColour[ i ].g, landColour[ i ].b, landColour[ i ].a } );

				for( int i = 0; i < landColourNoise.Length; ++i )
				{
					string id = ( i * 2 ).ToString() + ( i * 2 + 1 ).ToString();

					//land colour noise data
					noiseComputeShader.SetFloat( "landColour" + id + "Scale",			landColourNoise[ i ].scale );
					noiseComputeShader.SetInt( "landColour" + id + "Octaves",			landColourNoise[ i ].octaves );
					noiseComputeShader.SetFloat( "landColour" + id + "Falloff",			landColourNoise[ i ].falloff );
					noiseComputeShader.SetFloat( "landColour" + id + "Intensity",		landColourNoise[ i ].intensity );
					noiseComputeShader.SetFloat( "landColour" + id + "Ridginess",		landColourNoise[ i ].ridginess );
					noiseComputeShader.SetFloat( "landColour" + id + "SmearScale",		landColourNoise[ i ].smearScale );
					noiseComputeShader.SetInt( "landColour" + id + "SmearOctaves",		landColourNoise[ i ].smearOctaves );
					noiseComputeShader.SetFloat( "landColour" + id + "SmearFalloff",	landColourNoise[ i ].smearFalloff );
					noiseComputeShader.SetFloat( "landColour" + id + "SmearIntensity",	landColourNoise[ i ].smearIntensity );
				}

				//diffuse params
				noiseComputeShader.SetFloat( "cityReach",		_cityReach );
				noiseComputeShader.SetFloat( "cityHeight",		cityHeight );
				noiseComputeShader.SetFloats( "waterColour0",	new float[] { waterColour0.r, waterColour0.g, waterColour0.b, waterColour0.a } );
				noiseComputeShader.SetFloats( "waterColour1",	new float[] { waterColour1.r, waterColour1.g, waterColour1.b, waterColour1.a } );
				noiseComputeShader.SetFloat( "waterLevel",		waterLevel );
				noiseComputeShader.SetFloat( "waterSpecular",	waterSpecular );
				noiseComputeShader.SetFloat( "waterFalloff",	waterFalloff );
				noiseComputeShader.SetFloats( "iceColour",		new float[] { iceColour.r, iceColour.g, iceColour.b, iceColour.a } );
				noiseComputeShader.SetFloat( "iceReach",		_iceReach );
				noiseComputeShader.SetFloat( "iceHeight",		iceHeight );
				noiseComputeShader.SetFloat( "shadowRange",		shadowRange );
				noiseComputeShader.SetFloat( "shadowStrength",	shadowStrength );
				noiseComputeShader.SetFloat( "normalScale",		normalScale );
				
				int pixelsPerDispatch = pixelCount;

				if( pixelsPerDispatch > maxThreadsPerDispatch )
				{
					pixelsPerDispatch = maxThreadsPerDispatch;
					pixelsPerDispatch -= maxThreadsPerDispatch % diffuseThreadsPerGroup;
				}

				noiseComputeShader.SetInt( "threadOffset", 0 );

				_jobCount			= Mathf.CeilToInt( pixelCount / ( float ) pixelsPerDispatch );
				_jobStartedCount	= 1;	//first dispatch is below
				_jobCompletedCount	= 0;

				computeResultBuffer = new ComputeBuffer( pixelsPerDispatch * diffusePixelsPerThread, sizeof( int ) );
				noiseComputeShader.SetBuffer( _diffuseKernel, "resultData", computeResultBuffer );

				noiseComputeShader.Dispatch( _diffuseKernel, pixelsPerDispatch / diffuseThreadsPerGroup, 1, 1 );

				computeResultData = new int[ pixelsPerDispatch * diffusePixelsPerThread ];
			}
			else
			{
				int workerCount = SystemInfo.processorCount - 1;				//-1 to account for main thread

				if( workerCount > 0 )
					_worker = new Thread[ workerCount ];

				//a bit inefficient to have more jobs than workers but with multiple threads
				//per core nowadays it makes sense, also gives an easy way to measure progress
				_jobCount			= Mathf.Max( 32, ( workerCount + 1 ) * ( workerCount + 1 ) );
				_jobCount			= Mathf.Min( width, _jobCount );
				_jobStartedCount	= 0;
				_jobCompletedCount	= 0;
				_jobList			= new int[ _jobCount ];

				for( int i = 0; i < _jobCount; ++i )
					_jobList[ i ] = i;

				for( int i = 0; i < workerCount; ++i )
				{
					_worker[ i ] = new Thread( () => { while( doDiffuseWork() ); } );
					_worker[ i ].Start();
				}
			}
		}
		public void generateCloudNoise( int width, int height,
										PlanetNoise cloudParams,
										int cloudWorleyNoiseOctaves,
										float cloudWorleyNoiseFrequency,
										float cloudWorleyNoiseAmplitude,
										float cloudShadowRange,
										float cloudShadowStrength,
										Color cloudColour0,
										Color cloudColour1,
										float cloudSpin,
										float cloudNormalScale,
										bool preMultiplyAlpha )
		{
			_width						= width;
			_height						= height;
			_cloudWorleyNoiseOctaves	= cloudWorleyNoiseOctaves;
			_cloudWorleyNoiseFrequency	= cloudWorleyNoiseFrequency;
			_cloudWorleyNoiseAmplitude	= cloudWorleyNoiseAmplitude;
			_cloudShadowRange			= cloudShadowRange;
			_cloudShadowStrength		= cloudShadowStrength;
			_cloudParams				= cloudParams;
			_cloudColour0				= cloudColour0;
			_cloudColour1				= cloudColour1;
			_cloudSpin					= cloudSpin;
			_cloudNormalScale			= cloudNormalScale;
			_preMultiplyAlpha			= preMultiplyAlpha;

			//8 bytes per pixel - all colour data followed by all normal data
			//colour - r, g, b, a
			//normal - x, y, z, height
			int bytesPerPixel	= 8;
			int pixelCount		= width * height;

			if( cloudData == null || cloudData.Length != pixelCount * bytesPerPixel )
				cloudData = new byte[ pixelCount * bytesPerPixel ];

			if( useComputerShader )
			{
				noiseComputeShader.SetFloat( "width",	width );
				noiseComputeShader.SetFloat( "height",	height );

				//perlin noise data
				float[] gradArray	= perlinNoiseCloud.getGradArray();
				perlinGradBuffer	= new ComputeBuffer( gradArray.Length, sizeof( float ) );
				perlinGradBuffer.SetData( gradArray );
				noiseComputeShader.SetBuffer( _cloudKernel, "perlinGrad", perlinGradBuffer );

				uint[] permArray	= perlinNoiseCloud.getPermArray();
				perlinPermBuffer	= new ComputeBuffer( permArray.Length, sizeof( int ) );
				perlinPermBuffer.SetData( permArray );
				noiseComputeShader.SetBuffer( _cloudKernel, "perlinPerm", perlinPermBuffer );

				noiseComputeShader.SetInt( "cloudSeed", worleyNoiseCloud.seed );

				//cloud noise data
				noiseComputeShader.SetFloat( "cloudScale",			cloudParams.scale );
				noiseComputeShader.SetInt( "cloudOctaves",			cloudParams.octaves );
				noiseComputeShader.SetFloat( "cloudFalloff",		cloudParams.falloff );
				noiseComputeShader.SetFloat( "cloudIntensity",		cloudParams.intensity );
				noiseComputeShader.SetFloat( "cloudRidginess",		cloudParams.ridginess );
				noiseComputeShader.SetFloat( "cloudSmearScale",		cloudParams.smearScale );
				noiseComputeShader.SetInt( "cloudSmearOctaves",		cloudParams.smearOctaves );
				noiseComputeShader.SetFloat( "cloudSmearFalloff",	cloudParams.smearFalloff );
				noiseComputeShader.SetFloat( "cloudSmearIntensity",	cloudParams.smearIntensity );

				//cloud worley noise data
				noiseComputeShader.SetInt( "cloudWorleyNoiseOctaves",		_cloudWorleyNoiseOctaves );
				noiseComputeShader.SetFloat( "cloudWorleyNoiseFrequency",	_cloudWorleyNoiseFrequency );
				noiseComputeShader.SetFloat( "cloudWorleyNoiseAmplitude",	_cloudWorleyNoiseAmplitude );

				noiseComputeShader.SetFloat( "cloudShadowRange",	_cloudShadowRange );
				noiseComputeShader.SetFloat( "cloudShadowStrength",	_cloudShadowStrength );

				//cloud params
				noiseComputeShader.SetFloats( "cloudColour0",		new float[] { cloudColour0.r, cloudColour0.g, cloudColour0.b, cloudColour0.a } );
				noiseComputeShader.SetFloats( "cloudColour1",		new float[] { cloudColour1.r, cloudColour1.g, cloudColour1.b, cloudColour1.a } );
				noiseComputeShader.SetFloat( "cloudSpin",			cloudSpin );
				noiseComputeShader.SetFloat( "cloudNormalScale",	cloudNormalScale );
				noiseComputeShader.SetInt( "preMultiplyAlpha",		preMultiplyAlpha ? 1 : 0 );
				
				int pixelsPerDispatch = pixelCount;

				if( pixelsPerDispatch > maxThreadsPerDispatch )
				{
					pixelsPerDispatch = maxThreadsPerDispatch;
					pixelsPerDispatch -= maxThreadsPerDispatch % cloudThreadsPerGroup;
				}

				noiseComputeShader.SetInt( "threadOffset", 0 );

				_jobCount			= Mathf.CeilToInt( pixelCount / ( float ) pixelsPerDispatch );
				_jobStartedCount	= 1;	//first dispatch is below
				_jobCompletedCount	= 0;

				computeResultBuffer = new ComputeBuffer( pixelsPerDispatch * cloudPixelsPerThread, sizeof( int ) );
				noiseComputeShader.SetBuffer( _cloudKernel, "resultData", computeResultBuffer );

				noiseComputeShader.Dispatch( _cloudKernel, pixelsPerDispatch / cloudThreadsPerGroup, 1, 1 );

				computeResultData = new int[ pixelsPerDispatch * cloudPixelsPerThread ];
			}
			else
			{
				int workerCount = SystemInfo.processorCount - 1;				//-1 to account for main thread

				if( workerCount > 0 )
					_worker = new Thread[ workerCount ];

				//a bit inefficient to have more jobs than workers but with multiple threads
				//per core nowadays it makes sense, also gives an easy way to measure progress
				_jobCount			= Mathf.Max( 32, ( workerCount + 1 ) * ( workerCount + 1 ) );
				_jobCount			= Mathf.Min( width, _jobCount );
				_jobStartedCount	= 0;
				_jobCompletedCount	= 0;
				_jobList			= new int[ _jobCount ];

				for( int i = 0; i < _jobCount; ++i )
					_jobList[ i ] = i;

				for( int i = 0; i < workerCount; ++i )
				{
					_worker[ i ] = new Thread( () => { while( doCloudWork() ); } );
					_worker[ i ].Start();
				}
			}
		}
		private Color getSurfaceColour( Vector3 pos, PlanetNoise noiseParams, Color colour0, Color colour1, PlanetNoisePerlin perlinNoise )
		{
			float c			= sample( pos, noiseParams, perlinNoise );
			Color result	= Color.Lerp( colour0, colour1, 1f - c );
			return result;
		}
		private float getSurfaceHeight( Vector3 pos, PlanetNoise noiseParams, PlanetNoisePerlin perlinNoise )
		{
			float result = sample( pos, noiseParams, perlinNoise );
			return result;
		}
		public void OnEnable()
		{
			if( surfaceNoise == null )
			{
				surfaceNoise						= new PlanetNoise();
				landNoise							= new PlanetNoise();
				landColourNoise01					= new PlanetNoise();
				landColourNoise23					= new PlanetNoise();
				cloudNoise							= new PlanetNoise();


				seedSurface							= Random.Range( 0, int.MaxValue );
				seedLand							= Random.Range( 0, int.MaxValue );
				seedLandColour01					= Random.Range( 0, int.MaxValue );
				seedLandColour23					= Random.Range( 0, int.MaxValue );
				seedCity							= Random.Range( 0, int.MaxValue );
				seedCloud							= Random.Range( 0, int.MaxValue );


				surfaceNoise.scale					= 0.9f;
				surfaceNoise.octaves				= 10;
				surfaceNoise.falloff				= 4.94f;
				surfaceNoise.intensity				= 2.75f;
				surfaceNoise.ridginess				= 0.46f;
				surfaceNoise.smearScale				= 0.6f;
				surfaceNoise.smearOctaves			= 1;
				surfaceNoise.smearFalloff			= 7.9f;
				surfaceNoise.smearIntensity			= 0.8f;


				landNoise.scale						= 0.68f;
				landNoise.octaves					= 1;
				landNoise.falloff					= 3.74f;
				landNoise.intensity					= 3.09f;
				landNoise.ridginess					= 0f;
				landNoise.smearScale				= 2f;
				landNoise.smearOctaves				= 1;
				landNoise.smearFalloff				= 1.04f;
				landNoise.smearIntensity			= 1.61f;

				landColour0							= new Color( 152f / 255f, 107f / 255f, 71f / 255f );
				landColour1							= new Color( 69f / 255f, 43f / 255f, 22f / 255f );
				landColour2							= new Color( 0f / 255f, 20f / 255f, 0f / 255f );
				landColour3							= new Color( 11f / 255f, 64f / 255f, 11f / 255f );

				landColourNoise01.scale				= 0.49f;
				landColourNoise01.octaves			= 9;
				landColourNoise01.falloff			= 9.13f;
				landColourNoise01.intensity			= 16.16f;
				landColourNoise01.ridginess			= 0.234f;
				landColourNoise01.smearScale		= 19.76f;
				landColourNoise01.smearOctaves		= 1;
				landColourNoise01.smearFalloff		= 9.53f;
				landColourNoise01.smearIntensity	= 15.73f;

				landColourNoise23.scale				= 0.49f;
				landColourNoise23.octaves			= 9;
				landColourNoise23.falloff			= 9.13f;
				landColourNoise23.intensity			= 16.16f;
				landColourNoise23.ridginess			= 0.234f;
				landColourNoise23.smearScale		= 19.76f;
				landColourNoise23.smearOctaves		= 1;
				landColourNoise23.smearFalloff		= 9.53f;
				landColourNoise23.smearIntensity	= 15.73f;


				waterColour0						= new Color( 3f / 255f, 3f / 255f, 52f / 255f );
				waterColour1						= new Color( 0f / 255f, 0f / 255f, 88f / 255f );
				waterLevel							= 0.5f;
				waterSpecular						= 1f;
				waterFalloff						= 3.1f;


				iceColour							= new Color( 1f, 1f, 234f / 255f, 1f );
				iceReach							= 0.308f;
				iceHeight							= 0.986f;


				shadowRange							= 20f;
				shadowStrength						= 0.4f;


				cityReach							= 0.8f;
				cityHeight							= 0.8f;
				cityColour							= new Color( 37f / 255f, 27f / 255f, 17f / 255f );
				cityCount							= 128;
				cityMultiplier						= 6;
				cityDropoff							= 4;
				cityDepth							= 4;
				citySpread							= 0.45f;
				cityIntensity						= 64f;
				maxCityIntensity					= 7.5f;
				cityFalloff							= 0.5f;


				normalScale							= 0.1f;


				cloudNoise.scale					= 0.4f;
				cloudNoise.octaves					= 10;
				cloudNoise.falloff					= 4.1f;
				cloudNoise.intensity				= 6.1f;
				cloudNoise.ridginess				= 0f;
				cloudNoise.smearScale				= 16.38f;
				cloudNoise.smearOctaves				= 3;
				cloudNoise.smearFalloff				= 4.2f;
				cloudNoise.smearIntensity			= 5.15f;

				cloudWorleyNoiseOctaves				= 1;
				cloudWorleyNoiseFrequency			= 6f;
				cloudWorleyNoiseAmplitude			= 0.5f;

				cloudShadowRange					= 10f;
				cloudShadowStrength					= 0.1f;

				cloudColour0						= new Color( 1f, 1f, 1f, 1f );
				cloudColour1						= new Color( 0f, 0f, 0f, 0f );

				cloudSpin							= 1f;
				cloudNormalScale					= 0.01f;
				

				size								= 0;
				combineHeightWithCity				= true;
			}
		}
		public void randomiseNoise( PlanetNoise noise )
		{
			noise.scale				= Random.Range( 0.1f,	20f );
			noise.octaves			= Random.Range( 0,		10 );
			noise.falloff			= Random.Range( 0f,		20f );
			noise.intensity			= Random.Range( 0f,		20f );
			noise.ridginess			= Random.Range( 0f,		1f );
			noise.smearScale		= Random.Range( 0.1f,	20f );
			noise.smearOctaves		= Random.Range( 0,		10 );
			noise.smearFalloff		= Random.Range( 0f,		20f );
			noise.smearIntensity	= Random.Range( 0f,		20f );
		}