Perlin Noise

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Another function)
 
(7 intermediate revisions by 3 users not shown)
Line 5: Line 5:
 
== Usage ==
 
== Usage ==
 
Download the package. Open Unity with your own project folder. Double click on the unityPackage in the finder.
 
Download the package. Open Unity with your own project folder. Double click on the unityPackage in the finder.
[[Media:Noise_174.unitypackage.zip|Noise.unitypackage]]
+
[[http://unity3d.com/support/resources/example-projects/procedural-examples PerlinNoise]]
  
 
This installs the perlin noise class and 3 scripts implementing:
 
This installs the perlin noise class and 3 scripts implementing:
Line 14: Line 14:
 
To use one of the scripts, just drag them on a game object, to make them move, rotate, animate light based on noise.
 
To use one of the scripts, just drag them on a game object, to make them move, rotate, animate light based on noise.
  
== Perlin.cs Optimized by Tom Long ==
+
== Another function ==
 +
previous information above is out of date links
 +
here are 4 new functions including voronoi on a pretty free license
 +
[http://forum.unity3d.com/threads/68764-LibNoise-Ported-to-Unity?p=439185#post439185 UnityScript noises on forum]
  
The following code replaces the Perlin.cs file that is included in the package above. The package's Perlin.cs has
+
Also here is a nearly complete implementation of Perlin noise in UnityScript,although I didn't finish completing it because I didn't understand JavaScript this.noise function.
multiple divisions that have been replaced by multiplying by the inverse as a decimal. Comments are include to verify
+
I am sure I will finish it or else you can help if you want the original is here-
optimization methods.
+
[http://asserttrue.blogspot.co.uk/2011/12/perlin-noise-in-javascript_31.html JavaScript Perlin noise implementation]
  
[code]
+
<syntaxhighlight lang="javascript">
using System.Collections;
+
#pragma strict
using System;
+
using UnityEngine;
+
  
/* Perlin noise use example:
 
  
Perlin perlin = new Perlin();
+
// This is a port of Ken Perlin's Java code. The
var value : float = perlin.Noise(2);
+
// original Java code is at http://cs.nyu.edu/%7Eperlin/noise/.
var value : float = perlin.Noise(2, 3, );
+
// Note that in this version, a number from 0 to 1 is returned.
var value : float = perlin.Noise(2, 3, 4);
+
function PerlinNoise() {
 +
var x :int;
 +
var y :int;  
 +
var z :int;
 +
var t :int;
 +
var a :int;
 +
var b :int;
 +
var n :int;
 +
var hash :int;
 +
thisnoise (x, y, z);
 +
fade(t);
 +
lerp( t, a, b);
 +
grad(hash, x, y, z);
 +
    scale(n);}
  
 +
function thisnoise (x:int, y:int, z:int) {
  
SmoothRandom use example:
+
  var p : int[]; //array
 +
  p = new int[512];
 +
  var permutation : int[] = [ 151,160,137,91,90,15,
 +
  131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
 +
  190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
 +
  88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
 +
  77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
 +
  102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
 +
  135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
 +
  5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
 +
  223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
 +
  129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
 +
  251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
 +
  49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
 +
  138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
 +
  ];
 +
  for (var i=0; i < 256 ; i++)
 +
p[256+i] = p[i] = permutation[i];
  
var p = SmoothRandom.GetVector3(3);
+
    var X = parseInt(Mathf.Floor(x)) & 255;                  // FIND UNIT CUBE THAT
 +
var Y = parseInt(Mathf.Floor(y)) & 255;                // CONTAINS POINT.
 +
var Z = parseInt(Mathf.Floor(z)) & 255;
 +
      x -= Mathf.Floor(x);                                // FIND RELATIVE X,Y,Z
 +
      y -= Mathf.Floor(y);                                // OF POINT IN CUBE.
 +
      z -= Mathf.Floor(z);
 +
      var    u = fade(x);                              // COMPUTE FADE CURVES
 +
      var      v = fade(y);                              // FOR EACH OF X,Y,Z.
 +
      var      w = fade(z);
 +
      var A = p[X  ]+Y;var AA = p[A]+Z;var AB = p[A+1]+Z;      // HASH COORDINATES OF
 +
        var B = p[X+1]+Y;var BA = p[B]+Z;var BB = p[B+1]+Z;     // THE 8 CUBE CORNERS,
  
*/
+
      return scale(lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z  ),  // AND ADD
 +
                                    grad(p[BA  ], x-1, y  , z  )), // BLENDED
 +
                            lerp(u, grad(p[AB  ], x  , y-1, z  ),  // RESULTS
 +
                                    grad(p[BB  ], x-1, y-1, z  ))),// FROM  8
 +
                    lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  // CORNERS
 +
                                    grad(p[BA+1], x-1, y  , z-1 )), // OF CUBE
 +
                            lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
 +
                                    grad(p[BB+1], x-1, y-1, z-1 )))));
 +
  }
 +
  function fade(t:int) { return t * t * t * (t * (t * 6 - 15) + 10); }
 +
  function lerp( t:int, a:int, b:int) { return a + t * (b - a); }
 +
  function grad(hash:int, x:int, y:int, z:int) {
 +
      var h = hash & 15;                      // CONVERT LO 4 BITS OF HASH CODE
 +
      var u = h<8 ? x : y;                // INTO 12 GRADIENT DIRECTIONS.
 +
          var  v = h<4 ? y : h==12||h==14 ? x : z;
 +
      return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
 +
  }
 +
  function scale(n:int) { return (1 + n)/2; }
  
public class SmoothRandom
+
</syntaxhighlight>
{
+
// Range is between 0 and 1
+
public static Vector3 GetVector3 (float speed)
+
{
+
float time = Time.time * 0.01F * speed;
+
Vector3 value;
+
value.x = Get().HybridMultifractal(time, 15.73F, 0.58F);
+
value.y =  Get().HybridMultifractal(time, 63.94F, 0.58F);
+
value.z = Get().HybridMultifractal(time, 0.2F, 0.58F);
+
 
+
 
+
/* Division is expensive and can be replaced by multipling the inverse
+
value/0.6 can be replaced by value * 1/0.6 which is the same as value *= 1.666667
+
*/
+
// Approximately in the range  0 - 0.6
+
//value /= 0.6F;
+
value *= 1.666667F;
+
value = new Vector3 (Mathf.Clamp01(value.x), Mathf.Clamp01(value.y), Mathf.Clamp01(value.z));
+
return value;
+
}
+
+
public static float Get (float speed)
+
{
+
float time = Time.time * 0.01F * speed;
+
float value =  Get().HybridMultifractal(time, 15.7F, 0.58F);
+
 
+
/* Replacing division with multipling by the inverse as a decial
+
1/0.6 = 1.666667
+
*/
+
//value /= 0.6F;
+
value *= 1.666667F;
+
value = Mathf.Clamp01(value);
+
return value;
+
}
+
 
+
private static FractalNoise Get () {
+
if (s_Noise == null)
+
s_Noise = new FractalNoise (1.27F, 2.04F, 8.36F);
+
return s_Noise;
+
}
+
 
+
private static FractalNoise s_Noise;
+
}
+
 
+
public class Perlin
+
{
+
// Returns noise between 0 - 1
+
static public float NoiseNormalized(float x, float y)
+
{
+
//-0.697 - 0.795 + 0.697
+
float value = Noise(x, y);
+
+
/* Replacing division with multipling by the inverse as a decial
+
0.793+0.69 = 1.483
+
1/1.483 = 0.67430883345
+
*/
+
//value = (value + 0.69F) / (0.793F + 0.69F);
+
value = (value + 0.69F) *0.67430883345F;
+
        return value;
+
}
+
 
+
static public float Noise(float x, float y)
+
{
+
int X = (int)Mathf.Floor(x) & 255,                  // FIND UNIT CUBE THAT
+
Y = (int)Mathf.Floor(y) & 255;                  // CONTAINS POINT.
+
x -= Mathf.Floor(x);                                // FIND RELATIVE X,Y,Z
+
y -= Mathf.Floor(y);                                // OF POINT IN CUBE.
+
float u = fade(x),                                // COMPUTE FADE CURVES
+
v = fade(y);                                // FOR EACH OF X,Y,Z.
+
int A = p[X  ]+Y, AA = p[A], AB = p[A+1],      // HASH COORDINATES OF
+
B = p[X+1]+Y, BA = p[B], BB = p[B+1];      // THE 8 CUBE CORNERS,
+
+
float res = lerp(v, lerp(u, grad2(p[AA  ], x  , y  ),  // AND ADD
+
                                    grad2(p[BA  ], x-1, y )), // BLENDED
+
                            lerp(u, grad2(p[AB  ], x  , y-1 ),  // RESULTS
+
                                    grad2(p[BB  ], x-1, y-1 )));// FROM  8
+
                return res;
+
}
+
+
static public float Noise(float x, float y, float z) {
+
int X = (int)Mathf.Floor(x) & 255,                  // FIND UNIT CUBE THAT
+
Y = (int)Mathf.Floor(y) & 255,                  // CONTAINS POINT.
+
Z = (int)Mathf.Floor(z) & 255;
+
x -= Mathf.Floor(x);                                // FIND RELATIVE X,Y,Z
+
y -= Mathf.Floor(y);                                // OF POINT IN CUBE.
+
z -= Mathf.Floor(z);
+
float u = fade(x),                                // COMPUTE FADE CURVES
+
v = fade(y),                                // FOR EACH OF X,Y,Z.
+
w = fade(z);
+
int A = p[X  ]+Y, AA = p[A]+Z, AB = p[A+1]+Z,      // HASH COORDINATES OF
+
B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;      // THE 8 CUBE CORNERS,
+
+
return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z  ),  // AND ADD
+
grad(p[BA  ], x-1, y  , z  )), // BLENDED
+
lerp(u, grad(p[AB  ], x  , y-1, z  ),  // RESULTS
+
grad(p[BB  ], x-1, y-1, z  ))),// FROM  8
+
lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  // CORNERS
+
grad(p[BA+1], x-1, y  , z-1 )), // OF CUBE
+
lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
+
grad(p[BB+1], x-1, y-1, z-1 ))));
+
}
+
+
static float fade(float t) { return t * t * t * (t * (t * 6 - 15) + 10); }
+
static float lerp(float t, float a, float b) { return a + t * (b - a); }
+
static float grad(int hash, float x, float y, float z) {
+
int h = hash & 15;                      // CONVERT LO 4 BITS OF HASH CODE
+
float u = h<8 ? x : y,                // INTO 12 GRADIENT DIRECTIONS.
+
v = h<4 ? y : h==12||h==14 ? x : z;
+
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
+
}
+
 
+
static float grad2(int hash, float x, float y) {
+
int h = hash & 15;                      // CONVERT LO 4 BITS OF HASH CODE
+
float u = h < 8 ? x : y,                // INTO 12 GRADIENT DIRECTIONS.
+
v = h < 4 ? y : h==12 || h==14 ? x : 0;
+
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
+
}
+
+
static int[] p = { 151,160,137,91,90,15,
+
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
+
151,160,137,91,90,15,
+
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
+
};
+
}
+
 
+
/*
+
public class Perlin
+
{
+
// Original C code derived from
+
// http://astronomy.swin.edu.au/~pbourke/texture/perlin/perlin.c
+
// http://astronomy.swin.edu.au/~pbourke/texture/perlin/perlin.h
+
const int B = 0x100;
+
const int BM = 0xff;
+
const int N = 0x1000;
+
 
+
int[] p = new int[B + B + 2];
+
float[,] g3 = new float [B + B + 2 , 3];
+
float[,] g2 = new float[B + B + 2,2];
+
float[] g1 = new float[B + B + 2];
+
 
+
float s_curve(float t)
+
{
+
return t * t * (3.0F - 2.0F * t);
+
}
+
+
float lerp (float t, float a, float b)
+
{
+
return a + t * (b - a);
+
}
+
 
+
void setup (float value, out int b0, out int b1, out float r0, out float r1)
+
{
+
        float t = value + N;
+
        b0 = ((int)t) & BM;
+
        b1 = (b0+1) & BM;
+
        r0 = t - (int)t;
+
        r1 = r0 - 1.0F;
+
}
+
+
float at2(float rx, float ry, float x, float y) { return rx * x + ry * y; }
+
float at3(float rx, float ry, float rz, float x, float y, float z) { return rx * x + ry * y + rz * z; }
+
 
+
public float Noise(float arg)
+
{
+
int bx0, bx1;
+
float rx0, rx1, sx, u, v;
+
setup(arg, out bx0, out bx1, out rx0, out rx1);
+
+
sx = s_curve(rx0);
+
u = rx0 * g1[ p[ bx0 ] ];
+
v = rx1 * g1[ p[ bx1 ] ];
+
+
return(lerp(sx, u, v));
+
}
+
 
+
public float Noise(float x, float y)
+
{
+
int bx0, bx1, by0, by1, b00, b10, b01, b11;
+
float rx0, rx1, ry0, ry1, sx, sy, a, b, u, v;
+
int i, j;
+
+
setup(x, out bx0, out bx1, out rx0, out rx1);
+
setup(y, out by0, out by1, out ry0, out ry1);
+
+
i = p[ bx0 ];
+
j = p[ bx1 ];
+
+
b00 = p[ i + by0 ];
+
b10 = p[ j + by0 ];
+
b01 = p[ i + by1 ];
+
b11 = p[ j + by1 ];
+
+
sx = s_curve(rx0);
+
sy = s_curve(ry0);
+
+
u = at2(rx0,ry0, g2[ b00, 0 ], g2[ b00, 1 ]);
+
v = at2(rx1,ry0, g2[ b10, 0 ], g2[ b10, 1 ]);
+
a = lerp(sx, u, v);
+
+
u = at2(rx0,ry1, g2[ b01, 0 ], g2[ b01, 1 ]);
+
v = at2(rx1,ry1, g2[ b11, 0 ], g2[ b11, 1 ]);
+
b = lerp(sx, u, v);
+
+
return lerp(sy, a, b);
+
}
+
+
public float Noise(float x, float y, float z)
+
{
+
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+
float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
+
int i, j;
+
+
setup(x, out bx0, out bx1, out rx0, out rx1);
+
setup(y, out by0, out by1, out ry0, out ry1);
+
setup(z, out bz0, out bz1, out rz0, out rz1);
+
+
i = p[ bx0 ];
+
j = p[ bx1 ];
+
+
b00 = p[ i + by0 ];
+
b10 = p[ j + by0 ];
+
b01 = p[ i + by1 ];
+
b11 = p[ j + by1 ];
+
+
t  = s_curve(rx0);
+
sy = s_curve(ry0);
+
sz = s_curve(rz0);
+
+
u = at3(rx0,ry0,rz0, g3[ b00 + bz0, 0 ], g3[ b00 + bz0, 1 ], g3[ b00 + bz0, 2 ]);
+
v = at3(rx1,ry0,rz0, g3[ b10 + bz0, 0 ], g3[ b10 + bz0, 1 ], g3[ b10 + bz0, 2 ]);
+
a = lerp(t, u, v);
+
+
u = at3(rx0,ry1,rz0, g3[ b01 + bz0, 0 ], g3[ b01 + bz0, 1 ], g3[ b01 + bz0, 2 ]);
+
v = at3(rx1,ry1,rz0, g3[ b11 + bz0, 0 ], g3[ b11 + bz0, 1 ], g3[ b11 + bz0, 2 ]);
+
b = lerp(t, u, v);
+
+
c = lerp(sy, a, b);
+
+
u = at3(rx0,ry0,rz1, g3[ b00 + bz1, 0 ], g3[ b00 + bz1, 2 ], g3[ b00 + bz1, 2 ]);
+
v = at3(rx1,ry0,rz1, g3[ b10 + bz1, 0 ], g3[ b10 + bz1, 1 ], g3[ b10 + bz1, 2 ]);
+
a = lerp(t, u, v);
+
+
u = at3(rx0,ry1,rz1, g3[ b01 + bz1, 0 ], g3[ b01 + bz1, 1 ], g3[ b01 + bz1, 2 ]);
+
v = at3(rx1,ry1,rz1,g3[ b11 + bz1, 0 ], g3[ b11 + bz1, 1 ], g3[ b11 + bz1, 2 ]);
+
b = lerp(t, u, v);
+
+
d = lerp(sy, a, b);
+
+
return lerp(sz, c, d);
+
}
+
+
void normalize2(ref float x, ref float y)
+
{
+
  float s;
+
+
s = (float)Math.Sqrt(x * x + y * y);
+
x = y / s;
+
y = y / s;
+
}
+
+
void normalize3(ref float x, ref float y, ref float z)
+
{
+
float s;
+
s = (float)Math.Sqrt(x * x + y * y + z * z);
+
x = y / s;
+
y = y / s;
+
z = z / s;
+
}
+
+
public Perlin()
+
{
+
int i, j, k;
+
System.Random rnd = new System.Random();
+
+
  for (i = 0 ; i < B ; i++) {
+
  p[i] = i;
+
  g1[i] = (float)(rnd.Next(B + B) - B) / B;
+
+
  for (j = 0 ; j < 2 ; j++)
+
g2[i,j] = (float)(rnd.Next(B + B) - B) / B;
+
  normalize2(ref g2[i, 0], ref g2[i, 1]);
+
+
  for (j = 0 ; j < 3 ; j++)
+
g3[i,j] = (float)(rnd.Next(B + B) - B) / B;
+
+
+
  normalize3(ref g3[i, 0], ref g3[i, 1], ref g3[i, 2]);
+
  }
+
+
  while (--i != 0) {
+
  k = p[i];
+
  p[i] = p[j = rnd.Next(B)];
+
  p[j] = k;
+
  }
+
+
  for (i = 0 ; i < B + 2 ; i++) {
+
  p[B + i] = p[i];
+
  g1[B + i] = g1[i];
+
  for (j = 0 ; j < 2 ; j++)
+
g2[B + i,j] = g2[i,j];
+
  for (j = 0 ; j < 3 ; j++)
+
g3[B + i,j] = g3[i,j];
+
  }
+
}
+
}
+
*/
+
 
+
[System.Serializable]
+
public class FractalNoiseParams
+
{
+
public float h = 0.69F;
+
public float lacunarity = 6.18F;
+
public float octaves = 8.379F;
+
public float offset = 0.75F;
+
public float xScale = 1.0F;
+
public float yScale = 1.0F;
+
public float valueScale = 1.0F;
+
}
+
 
+
 
+
public class FractalNoise
+
{
+
void PrecalculateNOoise () {}
+
+
public FractalNoise (FractalNoiseParams para)
+
: this (para.h, para.lacunarity, para.octaves, null)
+
{
+
m_XScale = para.xScale;
+
m_YScale = para.yScale;
+
m_ValueScale = para.valueScale;
+
+
}
+
 
+
public FractalNoise (float inH, float inLacunarity, float inOctaves)
+
: this (inH, inLacunarity, inOctaves, null)
+
{
+
}
+
 
+
public FractalNoise (float inH, float inLacunarity, float inOctaves, Perlin noise)
+
{
+
m_Lacunarity = inLacunarity;
+
m_Octaves = inOctaves;
+
m_IntOctaves = (int)inOctaves;
+
m_Exponent = new float[m_IntOctaves+1];
+
float frequency = 1.0F;
+
for (int i = 0; i < m_IntOctaves+1; i++)
+
{
+
m_Exponent[i] = (float)Math.Pow (m_Lacunarity, -inH);
+
frequency *= m_Lacunarity;
+
}
+
}
+
+
+
public float HybridMultifractal(float x, float y, float offset)
+
{
+
x *= m_XScale;
+
y *= m_YScale;
+
+
float weight, signal, remainder, result;
+
+
result = (Perlin.Noise (x, y)+offset) * m_Exponent[0];
+
weight = result;
+
x *= m_Lacunarity;
+
y *= m_Lacunarity;
+
int i;
+
for (i=1;i<m_IntOctaves;i++)
+
{
+
if (weight > 1.0F) weight = 1.0F;
+
signal = (Perlin.Noise (x, y) + offset) * m_Exponent[i];
+
result += weight * signal;
+
weight *= signal;
+
x *= m_Lacunarity;
+
y *= m_Lacunarity;
+
}
+
remainder = m_Octaves - m_IntOctaves;
+
result += remainder * Perlin.Noise (x,y) * m_Exponent[i];
+
+
return result * m_ValueScale;
+
}
+
+
public float RidgedMultifractal (float x, float y, float offset, float gain)
+
{
+
x *= m_XScale;
+
y *= m_YScale;
+
 
+
float weight, signal, result;
+
int i;
+
+
signal = Mathf.Abs (Perlin.Noise (x, y));
+
signal = offset - signal;
+
signal *= signal;
+
result = signal;
+
weight = 1.0F;
+
+
for (i=1;i<m_IntOctaves;i++)
+
{
+
x *= m_Lacunarity;
+
y *= m_Lacunarity;
+
+
weight = signal * gain;
+
weight = Mathf.Clamp01 (weight);
+
+
signal = Mathf.Abs (Perlin.Noise (x, y));
+
signal = offset - signal;
+
signal *= signal;
+
signal *= weight;
+
result += signal * m_Exponent[i];
+
}
+
+
return result * m_ValueScale;
+
}
+
 
+
public float BrownianMotion (float x, float y)
+
{
+
x *= m_XScale;
+
y *= m_YScale;
+
+
float value, remainder;
+
long i;
+
+
value = 0.0F;
+
for (i=0;i<m_IntOctaves;i++)
+
{
+
value = Perlin.Noise (x,y) * m_Exponent[i];
+
x *= m_Lacunarity;
+
y *= m_Lacunarity;
+
}
+
remainder = m_Octaves - m_IntOctaves;
+
value += remainder * Perlin.Noise (x,y) * m_Exponent[i];
+
 
+
return value * m_ValueScale;
+
}
+
+
private float[] m_Exponent;
+
private int    m_IntOctaves;
+
private float  m_Octaves;
+
private float  m_Lacunarity;
+
private float  m_XScale = 1.0F;
+
private float  m_YScale = 1.0F;
+
private float  m_ValueScale = 1.0F;
+
}
+
/*
+
 
+
/// This is an alternative implementation of perlin noise
+
public class Noise
+
{
+
public float Noise(float x)
+
{
+
return Noise(x, 0.5F);
+
}
+
 
+
public float Noise(float x, float y)
+
{
+
int Xint = (int)x;
+
int Yint = (int)y;
+
float Xfrac = x - Xint;
+
float Yfrac = y - Yint;
+
 
+
float x0y0 = Smooth_Noise(Xint, Yint);  //find the noise values of the four corners
+
float x1y0 = Smooth_Noise(Xint+1, Yint);
+
float x0y1 = Smooth_Noise(Xint, Yint+1);
+
float x1y1 = Smooth_Noise(Xint+1, Yint+1);
+
 
+
//interpolate between those values according to the x and y fractions
+
float v1 = Interpolate(x0y0, x1y0, Xfrac); //interpolate in x direction (y)
+
float v2 = Interpolate(x0y1, x1y1, Xfrac); //interpolate in x direction (y+1)
+
float fin = Interpolate(v1, v2, Yfrac);  //interpolate in y direction
+
 
+
return fin;
+
}
+
 
+
private float Interpolate(float x, float y, float a)
+
{
+
float b = 1-a;
+
float fac1 = (float)(3*b*b - 2*b*b*b);
+
float fac2 = (float)(3*a*a - 2*a*a*a);
+
 
+
return x*fac1 + y*fac2; //add the weighted factors
+
}
+
 
+
private float GetRandomValue(int x, int y)
+
{
+
x = (x+m_nNoiseWidth) % m_nNoiseWidth;
+
y = (y+m_nNoiseHeight) % m_nNoiseHeight;
+
float fVal = (float)m_aNoise[(int)(m_fScaleX*x), (int)(m_fScaleY*y)];
+
return fVal/255*2-1f;
+
}
+
 
+
private float Smooth_Noise(int x, int y)
+
{
+
float corners = ( Noise2d(x-1, y-1) + Noise2d(x+1, y-1) + Noise2d(x-1, y+1) + Noise2d(x+1, y+1) ) / 16.0f;
+
float sides = ( Noise2d(x-1, y) +Noise2d(x+1, y) + Noise2d(x, y-1) + Noise2d(x, y+1) ) / 8.0f;
+
float center = Noise2d(x, y) / 4.0f;
+
return corners + sides + center;
+
}
+
 
+
private float Noise2d(int x, int y)
+
{
+
x = (x+m_nNoiseWidth) % m_nNoiseWidth;
+
y = (y+m_nNoiseHeight) % m_nNoiseHeight;
+
+
float fVal = (float)m_aNoise[(int)(m_fScaleX*x), (int)(m_fScaleY*y)];
+
+
return fVal/255*2-1f;
+
}
+
 
+
public Noise()
+
{
+
m_nNoiseWidth = 100;
+
m_nNoiseHeight = 100;
+
m_fScaleX = 1.0F;
+
m_fScaleY = 1.0F;
+
System.Random rnd = new System.Random();
+
m_aNoise = new int[m_nNoiseWidth,m_nNoiseHeight];
+
for (int x = 0; x<m_nNoiseWidth; x++)
+
{
+
for (int y = 0; y<m_nNoiseHeight; y++)
+
{
+
m_aNoise[x,y] = rnd.Next(255);
+
}
+
}
+
}
+
+
private int[,] m_aNoise;
+
protected int m_nNoiseWidth, m_nNoiseHeight;
+
private float m_fScaleX, m_fScaleY;
+
}
+
 
+
 
+
/* Yet another perlin noise implementation. This one is not even completely ported to C#
+
 
+
+
float noise1[];
+
float noise2[];
+
float noise3[];
+
int indices[];
+
 
+
float PerlinSmoothStep (float t)
+
{
+
return t * t * (3.0f - 2.0f * t);
+
}
+
+
float PerlinLerp(float t, float a, float b)
+
{
+
return a + t * (b - a);
+
}
+
+
float PerlinRand()
+
{
+
return Random.rand () / float(RAND_MAX)  * 2.0f - 1.0f;
+
}
+
+
+
PerlinNoise::PerlinNoise ()
+
{
+
long i, j, k;
+
float x, y, z, denom;
+
+
Random rnd = new Random();
+
 
+
+
noise1 = new float[1 * (PERLIN_B + PERLIN_B + 2)];
+
noise2 = new float[2 * (PERLIN_B + PERLIN_B + 2)];
+
noise3 = new float[3 * (PERLIN_B + PERLIN_B + 2)];
+
indices = new long[PERLIN_B + PERLIN_B + 2];
+
+
for (i = 0; i < PERLIN_B; i++)
+
{
+
indices[i] = i;
+
+
x = PerlinRand();
+
y = PerlinRand();
+
z = PerlinRand();
+
+
noise1[i] = x;
+
+
denom = sqrt(x * x + y * y);
+
if (denom > 0.0001f) denom = 1.0f / denom;
+
+
j = i << 1;
+
noise2[j + 0] = x * denom;
+
noise2[j + 1] = y * denom;
+
+
denom = sqrt(x * x + y * y + z * z);
+
if (denom > 0.0001f) denom = 1.0f / denom;
+
+
j += i;
+
noise3[j + 0] = x * denom;
+
noise3[j + 1] = y * denom;
+
noise3[j + 2] = z * denom;
+
}
+
+
while (--i != 0)
+
{
+
j = rand() & PERLIN_BITMASK;
+
std::swap (indices[i], indices[j]);
+
}
+
+
for (i = 0; i < PERLIN_B + 2; i++)
+
{
+
j = i + PERLIN_B;
+
+
indices[j] = indices[i];
+
+
noise1[j] = noise1[i];
+
+
j = j << 1;
+
k = i << 1;
+
noise2[j + 0] = noise2[k + 0];
+
noise2[j + 1] = noise2[k + 1];
+
+
j += i + PERLIN_B;
+
k += i + PERLIN_B;
+
noise3[j + 0] = noise3[k + 0];
+
noise3[j + 1] = noise3[k + 1];
+
noise3[j + 2] = noise3[k + 2];
+
}
+
}
+
+
PerlinNoise::~PerlinNoise ()
+
{
+
delete []noise1;
+
delete []noise2;
+
delete []noise3;
+
delete []indices;
+
}
+
+
void PerlinSetup (float v, long& b0, long& b1, float& r0, float& r1);
+
void PerlinSetup(
+
float v,
+
long& b0,
+
long& b1,
+
float& r0,
+
float& r1)
+
{
+
v += PERLIN_N;
+
+
long vInt = (long)v;
+
+
b0 = vInt & PERLIN_BITMASK;
+
b1 = (b0 + 1) & PERLIN_BITMASK;
+
r0 = v - (float)vInt;
+
r1 = r0 - 1.0f;
+
}
+
+
+
float PerlinNoise::Noise1 (float x)
+
{
+
long bx0, bx1;
+
float rx0, rx1, sx, u, v;
+
+
PerlinSetup(x, bx0, bx1, rx0, rx1);
+
+
sx = PerlinSmoothStep(rx0);
+
+
u = rx0 * noise1[indices[bx0]];
+
v = rx1 * noise1[indices[bx1]];
+
+
return PerlinLerp (sx, u, v);
+
}
+
+
float PerlinNoise::Noise2(float x, float y)
+
{
+
long bx0, bx1, by0, by1, b00, b01, b10, b11;
+
float rx0, rx1, ry0, ry1, sx, sy, u, v, a, b;
+
+
PerlinSetup (x, bx0, bx1, rx0, rx1);
+
PerlinSetup (y, by0, by1, ry0, ry1);
+
+
sx = PerlinSmoothStep (rx0);
+
sy = PerlinSmoothStep (ry0);
+
+
b00 = indices[indices[bx0] + by0] << 1;
+
b10 = indices[indices[bx1] + by0] << 1;
+
b01 = indices[indices[bx0] + by1] << 1;
+
b11 = indices[indices[bx1] + by1] << 1;
+
+
u = rx0 * noise2[b00 + 0] + ry0 * noise2[b00 + 1];
+
v = rx1 * noise2[b10 + 0] + ry0 * noise2[b10 + 1];
+
a = PerlinLerp (sx, u, v);
+
+
u = rx0 * noise2[b01 + 0] + ry1 * noise2[b01 + 1];
+
v = rx1 * noise2[b11 + 0] + ry1 * noise2[b11 + 1];
+
b = PerlinLerp (sx, u, v);
+
+
u = PerlinLerp (sy, a, b);
+
+
return u;
+
}
+
+
float PerlinNoise::Noise3(float x, float y, float z)
+
{
+
long bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+
float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
+
+
PerlinSetup (x, bx0, bx1, rx0, rx1);
+
PerlinSetup (y, by0, by1, ry0, ry1);
+
PerlinSetup (z, bz0, bz1, rz0, rz1);
+
+
b00 = indices[indices[bx0] + by0] << 1;
+
b10 = indices[indices[bx1] + by0] << 1;
+
b01 = indices[indices[bx0] + by1] << 1;
+
b11 = indices[indices[bx1] + by1] << 1;
+
 
+
t = PerlinSmoothStep (rx0);
+
sy = PerlinSmoothStep (ry0);
+
sz = PerlinSmoothStep (rz0);
+
+
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
+
+
q = &noise3[b00 + bz0]; u = at3(rx0,ry0,rz0);
+
q = &noise3[b10 + bz0]; v = at3(rx1,ry0,rz0);
+
a = PerlinLerp(t, u, v);
+
+
q = &noise3[b01 + bz0]; u = at3(rx0,ry1,rz0);
+
q = &noise3[b11 + bz0]; v = at3(rx1,ry1,rz0);
+
b = PerlinLerp(t, u, v);
+
+
c = PerlinLerp(sy, a, b);
+
+
q = &noise3[b00 + bz1]; u = at3(rx0,ry0,rz1);
+
q = &noise3[b10 + bz1]; v = at3(rx1,ry0,rz1);
+
a = PerlinLerp(t, u, v);
+
+
q = &noise3[b01 + bz1]; u = at3(rx0,ry1,rz1);
+
q = &noise3[b11 + bz1]; v = at3(rx1,ry1,rz1);
+
b = PerlinLerp(t, u, v);
+
+
d = PerlinLerp(sy, a, b);
+
+
return PerlinLerp (sz, c, d);
+
}
+
*/
+
[/code]
+

Latest revision as of 04:01, 23 October 2012

[edit] Description

The following snippet shows how to use noise for smoothly randomly moving objects, rotating them or animated light intensity.

[edit] Usage

Download the package. Open Unity with your own project folder. Double click on the unityPackage in the finder. [PerlinNoise]

This installs the perlin noise class and 3 scripts implementing:

  1. Animated light intensity noise
  2. Animated noise position
  3. Animated noise rotation

To use one of the scripts, just drag them on a game object, to make them move, rotate, animate light based on noise.

[edit] Another function

previous information above is out of date links here are 4 new functions including voronoi on a pretty free license UnityScript noises on forum

Also here is a nearly complete implementation of Perlin noise in UnityScript,although I didn't finish completing it because I didn't understand JavaScript this.noise function. I am sure I will finish it or else you can help if you want the original is here- JavaScript Perlin noise implementation

#pragma strict
 
 
// This is a port of Ken Perlin's Java code. The
// original Java code is at http://cs.nyu.edu/%7Eperlin/noise/.
// Note that in this version, a number from 0 to 1 is returned.
function PerlinNoise() {
var x :int;
var y :int; 
var z :int;
var t :int;
var a :int;
var b :int;
var n :int;
var hash :int;
	 thisnoise (x, y, z);
	 fade(t);
	 lerp( t, a, b);
	 grad(hash, x, y, z);
     scale(n);}
 
function thisnoise (x:int, y:int, z:int) {
 
   var p : int[]; //array
   p = new int[512];
   var permutation : int[] = [ 151,160,137,91,90,15,
   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
   ];
   for (var i=0; i < 256 ; i++) 
 p[256+i] = p[i] = permutation[i]; 
 
     var X = parseInt(Mathf.Floor(x)) & 255;                  // FIND UNIT CUBE THAT
	 var Y = parseInt(Mathf.Floor(y)) & 255;                // CONTAINS POINT.
	 var Z = parseInt(Mathf.Floor(z)) & 255;
      x -= Mathf.Floor(x);                                // FIND RELATIVE X,Y,Z
      y -= Mathf.Floor(y);                                // OF POINT IN CUBE.
      z -= Mathf.Floor(z);
      var    u = fade(x);                               // COMPUTE FADE CURVES
       var      v = fade(y);                               // FOR EACH OF X,Y,Z.
      var       w = fade(z);
      var A = p[X  ]+Y;var AA = p[A]+Z;var AB = p[A+1]+Z;      // HASH COORDINATES OF
         var B = p[X+1]+Y;var BA = p[B]+Z;var BB = p[B+1]+Z;      // THE 8 CUBE CORNERS,
 
      return scale(lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ),  // AND ADD
                                     grad(p[BA  ], x-1, y  , z   )), // BLENDED
                             lerp(u, grad(p[AB  ], x  , y-1, z   ),  // RESULTS
                                     grad(p[BB  ], x-1, y-1, z   ))),// FROM  8
                     lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  // CORNERS
                                     grad(p[BA+1], x-1, y  , z-1 )), // OF CUBE
                             lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
                                     grad(p[BB+1], x-1, y-1, z-1 )))));
   }
   function fade(t:int) { return t * t * t * (t * (t * 6 - 15) + 10); }
   function lerp( t:int, a:int, b:int) { return a + t * (b - a); }
   function grad(hash:int, x:int, y:int, z:int) {
      var h = hash & 15;                      // CONVERT LO 4 BITS OF HASH CODE
      var u = h<8 ? x : y;                 // INTO 12 GRADIENT DIRECTIONS.
           var  v = h<4 ? y : h==12||h==14 ? x : z;
      return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
   } 
   function scale(n:int) { return (1 + n)/2; }
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox