我尝试制作像this video这样的流星, 但我只能这样:
这是我的单纯噪音:
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)));
}
}
}
}
}
我在各个页面,博客和这里找到了相关信息,但发现没有任何对我有用的信息。如果有人有信息,我将非常感谢您的帮助。
感谢您帮助我。
答案 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之间的视觉差异: