在团结中实施Scape的“程序基础”Perlin噪音

时间:2013-02-11 04:56:44

标签: c# unity3d noise

尝试使用Unity实现C#中以下文章中的噪声函数:http://www.decarpentier.nl/scape-procedural-basics

它主要起作用,但是在x访问中混合时必定是错误的,因为地形是在乐队中生成的。

Terrain generated with current noise function

public void AddPerlinNoise(float scale=4.0f)
{
    for (int i = 0; i < Width; i++){
        for (int j = 0; j < Height; j++){
            float l = PerlinNoise(new Vector2(((float)i/(float)Width)*scale,((float)j/(float)Height)*scale));

            Heights[i, j] += l;
        }
    }
}

private float PerlinNoise(Vector2 p){
    Color col;

    // Calculate 2D integer coordinates i and fraction p.
    Vector2 i = new Vector2(Mathf.Floor(p.x),Mathf.Floor(p.y));
    Vector2 f = p - i;

    // Get weights from the coordinate fraction
    //float2 w = f * f * f * (f * (f * 6 - 15) + 10);
    Vector2 w = new Vector2(f.x * f.x * f.x * (f.x * (f.x * 6.0f - 15.0f) + 10.0f),f.y * f.y * f.y * (f.y * (f.y * 6.0f - 15.0f) + 10.0f));

    Vector4 w4 = new Vector4(1, w.x, w.y, w.x * w.y);

    // Get the four randomly permutated indices from the noise lattice nearest to
    // p and offset these numbers with the seed number.
    col = permTex.GetPixel((int)i.x,(int)i.y);

    Vector4 perm = new Vector4(col.r,col.g,col.b,col.a);

    Vector4 one = new Vector4(1,1,1,1);
    Vector4 two = new Vector4(2,2,2,2);

    // Permutate the four offseted indices again and get the 2D gradient for each
    // of the four permutated coordinates-seed pairs.
    col = gradTex.GetPixel((int)(perm.x*255.0f),(int)(perm.y*255.0f));
    Vector4 g1 = new Vector4(col.r,col.g,col.b,col.a);
    g1.Scale(two);
    g1 = g1 - one;
    col = gradTex.GetPixel((int)(perm.z*255.0f),(int)(perm.w*255.0f));
    Vector4 g2 = new Vector4(col.r,col.g,col.b,col.a);
    g2.Scale(two);
    g2 = g2 - one;

    // Evaluate the four lattice gradients at p
    float a = Vector2.Dot(new Vector2(g1.x,g1.y), f);
    float b = Vector2.Dot(new Vector2(g2.x,g2.y), f + new Vector2(-1,  0));
    float c = Vector2.Dot(new Vector2(g1.z,g1.w), f + new Vector2( 0, -1));
    float d = Vector2.Dot(new Vector2(g2.z,g2.w), f + new Vector2(-1, -1));

    // Bi-linearly blend between the gradients, using w4 as blend factors.
    Vector4 grads = new Vector4(a, b - a, c - a, a - b - c + d);
    float n = Vector4.Dot(grads, w4);

    // Return the noise value, roughly normalized in the range [0, 1]
    return (n * 1.5f) / 2 + 0.5f;
}

1 个答案:

答案 0 :(得分:0)

解决方案是在访问Texture2D像素值时翻转y轴。通过255 - y代替。

private float PerlinNoise(Vector2 p){
    Color col;

    // Calculate 2D integer coordinates i and fraction p.
    Vector2 i = new Vector2(Mathf.Floor(p.x),Mathf.Floor(p.y));
    Vector2 f = p - i;

    // Get weights from the coordinate fraction
    //float2 w = f * f * f * (f * (f * 6 - 15) + 10);
    Vector2 w = new Vector2(f.x * f.x * f.x * (f.x * (f.x * 6.0f - 15.0f) + 10.0f),f.y * f.y * f.y * (f.y * (f.y * 6.0f - 15.0f) + 10.0f));

    Vector4 w4 = new Vector4(1, w.x, w.y, w.x * w.y);

    // Get the four randomly permutated indices from the noise lattice nearest to
    // p and offset these numbers with the seed number.
    col = permTex.GetPixel((int)i.x,255 - (int)i.y);

    Vector4 perm = new Vector4(col.r,col.g,col.b,col.a);

    Vector4 one = new Vector4(1,1,1,1);
    Vector4 two = new Vector4(2,2,2,2);

    // Permutate the four offseted indices again and get the 2D gradient for each
    // of the four permutated coordinates-seed pairs.
    col = gradTex.GetPixel((int)(perm.x*255.0f),255 - (int)(perm.y*255.0f));
    Vector4 g1 = new Vector4(col.r,col.g,col.b,col.a);
    g1.Scale(two);
    g1 = g1 - one;
    col = gradTex.GetPixel((int)(perm.z*255.0f),255 - (int)(perm.w*255.0f));
    Vector4 g2 = new Vector4(col.r,col.g,col.b,col.a);
    g2.Scale(two);
    g2 = g2 - one;

    // Evaluate the four lattice gradients at p
    float a = Vector2.Dot(new Vector2(g1.x,g1.y), f);
    float b = Vector2.Dot(new Vector2(g2.x,g2.y), f + new Vector2(-1,  0));
    float c = Vector2.Dot(new Vector2(g1.z,g1.w), f + new Vector2( 0, -1));
    float d = Vector2.Dot(new Vector2(g2.z,g2.w), f + new Vector2(-1, -1));

    // Bi-linearly blend between the gradients, using w4 as blend factors.
    Vector4 grads = new Vector4(a, b - a, c - a, a - b - c + d);
    float n = Vector4.Dot(grads, w4);

    // Return the noise value, roughly normalized in the range [0, 1]
    return (n * 1.5f) / 2 + 0.5f;
}