具有单一噪声的陨石发电机

时间:2014-11-11 02:43:19

标签: c# unity3d simplex-noise

我尝试制作像this video这样的流星, 但我只能这样:

http://johannes.gotlen.se/blog/wp-content/uploads/2011/07/MarchingTetrahedonsSimplexNoise.png

这是我的单纯噪音:

public class PerlinNoise{
int B = 256;
int[] m_perm = new int[B+B];
Texture2D m_permTex;
public int octava;
public float frequencia, amplitud;

public PerlinNoise(int seed, float frec, float amp, int oct)
{
    octava = oct;
    amplitud = amp;
    frequencia = frec;
    UnityEngine.Random.seed = seed;

     int i, j, k;
    for (i = 0 ; i < B ; i++) 
     {
        m_perm[i] = i;
    }

     while (--i != 0) 
    {
        k = m_perm[i];
        j = UnityEngine.Random.Range(0, B);
        m_perm[i] = m_perm[j];
        m_perm[j] = k;
     }

    for (i = 0 ; i < B; i++) 
    {
        m_perm[B + i] = m_perm[i];
    }

 }

float FADE(float t) { return t * t * t * ( t * ( t * 6.0f - 15.0f ) + 10.0f ); }

float LERP(float t, float a, float b) { return (a) + (t)*((b)-(a)); }

float GRAD1(int hash, float x ) 
{
    int h = hash & 15;
    float grad = 1.0f + (h & 7);
    if ((h&8) != 0) grad = -grad;
    return ( grad * x );
}

float GRAD2(int hash, float x, float y)
{       
    int h = hash & 7;
    float u = h<4 ? x : y;
    float v = h<4 ? y : x;
    return (((h&1) != 0)? -u : u) + (((h&2) != 0) ? -2.0f*v : 2.0f*v);
}


float GRAD3(int hash, float x, float y , float z)
{


    int h = hash & 15;
    float u = h<8 ? x : y;
    float v = (h<4) ? y : (h==12 || h==14) ? x : z;
    return (((h&1) != 0)? -u : u) + (((h&2) != 0)? -v : v);
}

float Noise1D( float x )
{
    //returns a noise value between -0.5 and 0.5
    int ix0, ix1;
    float fx0, fx1;
    float s, n0, n1;

    ix0 = (int)Mathf.Floor(x);  // Integer part of x
    fx0 = x - ix0;          // Fractional part of x
    fx1 = fx0 - 1.0f;
    ix1 = ( ix0+1 ) & 0xff;
    ix0 = ix0 & 0xff;       // Wrap to 0..255

    s = FADE(fx0);

    n0 = GRAD1(m_perm[ix0], fx0);
    n1 = GRAD1(m_perm[ix1], fx1);
    return 0.188f * LERP( s, n0, n1);
}

public float Noise2D( float x, float y )
{

    int ix0, iy0, ix1, iy1;
    float fx0, fy0, fx1, fy1, s, t, nx0, nx1, n0, n1;

    ix0 = (int)Mathf.Floor(x); 
    iy0 = (int)Mathf.Floor(y);  
    fx0 = x - ix0;        
    fy0 = y - iy0;      
    fx1 = fx0 - 1.0f;
    fy1 = fy0 - 1.0f;
    ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255
    iy1 = (iy0 + 1) & 0xff;
    ix0 = ix0 & 0xff;
     iy0 = iy0 & 0xff;

    t = FADE( fy0 );
    s = FADE( fx0 );

    nx0 = GRAD2(m_perm[ix0 + m_perm[iy0]], fx0, fy0);
    nx1 = GRAD2(m_perm[ix0 + m_perm[iy1]], fx0, fy1);

    n0 = LERP( t, nx0, nx1 );

    nx0 = GRAD2(m_perm[ix1 + m_perm[iy0]], fx1, fy0);
    nx1 = GRAD2(m_perm[ix1 + m_perm[iy1]], fx1, fy1);

    n1 = LERP(t, nx0, nx1);

    return 0.507f * LERP( s, n0, n1 );
 }

float Noise3D( float x, float y, float z )
{
    //returns a noise value between -1.5 and 1.5
    int ix0, iy0, ix1, iy1, iz0, iz1;
    float fx0, fy0, fz0, fx1, fy1, fz1;
    float s, t, r;
    float nxy0, nxy1, nx0, nx1, n0, n1;

    ix0 = (int)Mathf.Floor( x ); // Integer part of x
    iy0 = (int)Mathf.Floor( y ); // Integer part of y
    iz0 = (int)Mathf.Floor( z ); // Integer part of z
    fx0 = x - ix0;        // Fractional part of x
    fy0 = y - iy0;        // Fractional part of y
    fz0 = z - iz0;        // Fractional part of z
    fx1 = fx0 - 1.0f;
    fy1 = fy0 - 1.0f;
    fz1 = fz0 - 1.0f;
    ix1 = ( ix0 + 1 ) & 0xff; // Wrap to 0..255
    iy1 = ( iy0 + 1 ) & 0xff;
    iz1 = ( iz0 + 1 ) & 0xff;
    ix0 = ix0 & 0xff;
    iy0 = iy0 & 0xff;
     iz0 = iz0 & 0xff;

     r = FADE( fz0 );
     t = FADE( fy0 );
    s = FADE( fx0 );

    nxy0 = GRAD3(m_perm[ix0 + m_perm[iy0 + m_perm[iz0]]], fx0, fy0, fz0);
     nxy1 = GRAD3(m_perm[ix0 + m_perm[iy0 + m_perm[iz1]]], fx0, fy0, fz1);
    nx0 = LERP( r, nxy0, nxy1 );

    nxy0 = GRAD3(m_perm[ix0 + m_perm[iy1 + m_perm[iz0]]], fx0, fy1, fz0);
     nxy1 = GRAD3(m_perm[ix0 + m_perm[iy1 + m_perm[iz1]]], fx0, fy1, fz1);
    nx1 = LERP( r, nxy0, nxy1 );

    n0 = LERP( t, nx0, nx1 );

     nxy0 = GRAD3(m_perm[ix1 + m_perm[iy0 + m_perm[iz0]]], fx1, fy0, fz0);
    nxy1 = GRAD3(m_perm[ix1 + m_perm[iy0 + m_perm[iz1]]], fx1, fy0, fz1);
     nx0 = LERP( r, nxy0, nxy1 );

    nxy0 = GRAD3(m_perm[ix1 + m_perm[iy1 + m_perm[iz0]]], fx1, fy1, fz0);
        nxy1 = GRAD3(m_perm[ix1 + m_perm[iy1 + m_perm[iz1]]], fx1, fy1, fz1);
    nx1 = LERP( r, nxy0, nxy1 );

    n1 = LERP( t, nx0, nx1 );

    return 0.936f * LERP( s, n0, n1 );
}

public float FractalNoise1D(float x, int octNum, float frq, float amp)
{
    float gain = 1.0f;
    float sum = 0.0f;

    for(int i = 0; i < octNum; i++)
    {
        sum +=  Noise1D(x*gain/frq) * amp/gain;
        gain *= 2.0f;
    }
    return sum;
}

public float FractalNoise2D(float x, float y, int octNum, float frq, float amp)
{
    float gain = 1.0f;
    float sum = 0.0f;

    for(int i = 0; i < octNum; i++)
    {
        sum += Noise2D(x*gain/frq, y*gain/frq) * amp/gain;
        gain *= 2.0f;
    }
     return sum;
}
public int Noise2D(Vector3Int v3) {
    return Mathf.RoundToInt(FractalNoise2D(v3.x,v3.z,octava,frequencia,amplitud));
}
public int Noise2D(int x, int z)
{
    return Mathf.RoundToInt(FractalNoise2D(x, z, octava, frequencia, amplitud));
}
public float FractalNoise3D(float x, float y, float z, int octNum, float frq, float amp)
{
    float gain = 1.0f;
    float sum = 0.0f;

    for(int i = 0; i < octNum; i++)
    {
        sum +=  Noise3D(x*gain/frq, y*gain/frq, z*gain/frq) * amp/gain;
        gain *= 2.0f;
    }
    return sum;
}

public void LoadPermTableIntoTexture()
{
    m_permTex = new Texture2D(256, 1, TextureFormat.Alpha8, false);
    m_permTex.filterMode = FilterMode.Point;
    m_permTex.wrapMode = TextureWrapMode.Clamp;

    for(int i = 0; i < 256; i++)
    {
        float v = (float)m_perm[i] / 255.0f;

        m_permTex.SetPixel(i, 0, new Color(0,0,0,v));
    }

    m_permTex.Apply();
}
}

这是我的实施:

public void Resimulate() {
  PerlinNoise per = new PerlinNoise(seed, frec, amp, octa);

    for (int x = 0; x < TamX; x++)
    {
        for (int y = 0; y < TamY; y++)
        {
            for (int z = 0; z < TamZ; z++)
            {
                if (per.FractalNoise3D(x, y, z, octa, frec, amp)>0)
                {
                 lista.Add(new Bloque(new Vector3Int(x, y, z)));
                }

            }
        }
     }     
 }

我在各个页面,博客和这里找到了相关信息,但发现没有任何对我有用的信息。如果有人有信息,我将非常感谢您的帮助。

感谢您帮助我。

1 个答案:

答案 0 :(得分:2)

首先,重要的是要注意你拥有的代码不是单纯形噪音!这是较旧的“Perlin噪声”算法,往往会出现视觉上显着的方向性伪影。

我建议完全避免Perlin噪音和Simplex噪音。 Perlin因为方向性工件和Simplex,因为你遇到了3D实现的专利问题。

我最近设计了一种算法来解决这两个问题,这些算法开始被相当数量的游戏开发者采用,称为OpenSimplex噪音。代码:https://gist.github.com/KdotJPG/b1270127455a94ac5d19

(编辑:这是一个C#端口:https://gist.github.com/omgwtfgames/601497972e4e30fd9c5f

做这样的事情:

const double S = 24; //Sparsity of noise features
public void Resimulate() {
    //To get fractal noise, ideally you want multiple instances of noise so you don't get odd behavior near (0,0,0)
    OpenSimplexNoise n1 = new OpenSimplexNoise(seed);
    OpenSimplexNoise n2 = new OpenSimplexNoise(seed+1);
    OpenSimplexNoise n3 = new OpenSimplexNoise(seed+2);

    for (int x = 0; x < TamX; x++) {
        for (int y = 0; y < Tamy; z++) {
            for (int z = 0; z < TamZ; z++) {
                double n = (n1.eval(x / S, y / S, z / S)
                    + n2.eval(x / S / 2, y / S / 2, z / S / 2) * .5
                    + n3.eval(x / S / 4, y / S / 4, z / S / 4) * .25)
                    / (1 + .5 + .25);
                double dx = (TamX / 2.0 - x);
                double dy = (TamY / 2.0 - y);
                double dz = (TamZ / 2.0 - z);
                double d = dx*dx + dy*dy + dz*dz;

                //d is now your squared distance from the center.
                //n is your fractal noise value
                //you want to combine d and n to form some threshold that
                //determines whether or not there is a block.
                //threshold = d / C1 + n + C2 > 0 where C1 and C2 are constants you choose
            }
        }
    }
}

编辑:这是Perlin和OpenSimplex之间的视觉差异:

enter image description here

  • 左边是噪声(x,y,0)灰度
  • 接下来是噪声(x,y,0)&gt; 0?白色:黑色
  • 接下来是| noise(x,y,0)| &GT; 0.1?白色:黑色
  • 接下来是噪声(x,y,0.5)灰度
相关问题