【问题标题】:Perlin noise generating visible "blocky" formations, JavaPerlin 噪声产生可见的“块状”结构,Java
【发布时间】:2014-10-06 15:28:34
【问题描述】:

根据this 文章,我一直在尝试在 java 中实现 perlin 噪声生成器。 Homever,我的发生器产生的噪音不是连续的,而是"blocky",在每个偶数坐标之间形成可见线。以下是我当前的代码:

private static final Point[] grads = {
    new Point(1, 0), new Point(-1, 0), new Point(0, 1), new Point(0, -1),
    new Point(1, 1), new Point(1, -1), new Point(-1, 1), new Point(-1, -1)
};

private int permutations[] = new int[512];

private int frequency;
private int seed;
private double[][] heightMap;
private double amplitude;

public PerlinNoise(int frequency, int seed, double[][] heightMap, double amplitude) {
    this.frequency = frequency;
    this.seed = seed; //Seed for randomizing the permutation table
    this.heightMap = heightMap; //The Heightmap where the finalt result will be stored
    this.amplitude = amplitude;
}

private void seedPermutationTables() {
    LinkedList<PermutationValue> l = new LinkedList<PermutationValue>();
    Random rand = new Random(this.seed);
    for (int i = 0; i < 256; i++) {
        l.add(new PermutationValue(i, rand));
    }
    Collections.sort(l);
    for (int i = 0; i < 512; i++) {
        permutations[i] = l.get(i & 255).getValue();
    }
}

public void generateNoise() {
    this.seedPermutationTables();
    int sWidth = this.heightMap.length / frequency;
    int sHeight = this.heightMap[0].length / frequency;
    for (int i = 0; i < this.heightMap.length; i++) {
        for (int j = 0; j < this.heightMap[i].length; j++) {
            double x = (double)i / sWidth;
            double y = (double)j / sHeight;
            this.heightMap[i][j] = this.noise(x, y);
        }
    }
}

private double noise(double x, double y) {
    int xi = (int)x & 255;
    int yi = (int)y & 255;
    double xf = x - (int)x;
    double yf = y - (int)y;

    double u = this.fade(xf);
    double v = this.fade(yf);

    int aa = permutations[permutations[xi] + yi];               
    int ab = permutations[permutations[xi] + yi + 1];           
    int ba = permutations[permutations[xi + 1] + yi];           
    int bb = permutations[permutations[xi + 1] + yi + 1];       

    double x1 = this.lerp(this.grad(aa, xf, yf), this.grad(ab, xf - 1, yf), u);
    double x2 = this.lerp(this.grad(ba, xf, yf - 1), this.grad(bb, xf - 1, yf - 1), u);
    double noise = this.lerp(x1, x2, v);
    return (1D + noise) / 2 * this.amplitude;   //The noise returns values between -1 and 1
                                                //So we change the range to 0-amplitude
}

private double grad(int hash, double x, double y) {
    hash = hash & 7;
    Point p = grads[hash];
    return p.x * x + p.y * y;
}

private double lerp(double a, double b, double x) {
    return a + x * (b - a);
}

private double fade(double x) {
    return x * x * x * (x * (x * 6 - 15) + 10);
}

private class PermutationValue implements Comparable<PermutationValue> {
    private int value;
    private double sortValue;

    public PermutationValue(int value, Random rand) {
        this.setValue(value);
        this.sortValue = rand.nextDouble();
    }

    @Override
    public int compareTo(PermutationValue pv) {
        if (pv.sortValue > this.sortValue) {
            return -1;
        }
        return 1;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    } 
}

高度图数组只是存储每个像素的高度值。有什么建议或想法可能导致这些形成?

【问题讨论】:

    标签: java perlin-noise procedural-generation


    【解决方案1】:

    哈希表可以用 rndng fct 中的 1-2 次乘法替换: 块状可能来自哈希表中缺少三次插值或数字噪声。 在您的情况下,这听起来像是在哈希表的两个值之间没有影响。 lerp 只取任意 2 个值并在它们之间进行平滑处理。所以如果运行不正常,那就是块状。

    function rndng ( n: float ): float //total noise pseudo
    {//random proportion -1, 1
        var e = ( n *321.9)%1;
        return  (e*e*111.0)%2-1;
    }
    
    
    function lerps(o:float, v:float, alpha:float):float
    {
        o += ( v - o ) * alpha;
        return o;
    }
    
    function lnz ( vtx: Vector3 ): float//3d noise
    {   
        vtx= Vector3 ( Mathf.Abs(vtx.x) , Mathf.Abs(vtx.y) , Mathf.Abs(vtx.z) ) ;
        var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
        var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
        D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
        var W = I.x + I.y*71.0 + 125.0*I.z;
    
        return lerps(           
                    lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.y)
                    ,
                    lerps( lerps(rndng(W+125.0),rndng(W+126.0),D.x) , lerps(rndng(W+153.0),rndng(W+154.0),D.x) , D.y)
                    ,
                    D.z
                    );
    }
    
    function lnzo ( vtx: Vector3 ): float
    {
        var total = 0.0;    
        for (var i:int = 1; i < 5; i ++)
        {
            total+= lnz2(Vector3 (vtx.x*(i*i),0.0,vtx.z*(i*i)))/(i*i);
        }
    
        return total*5;
    
    }
    function lnzh ( vtx: Vector3 ): float//3 axis 3d noise
    {   
        vtx= Vector3 ( Mathf.Abs(vtx.z) , Mathf.Abs(vtx.z*.5-vtx.x*.866) , Mathf.Abs(vtx.z*.5+vtx.x*.866) ) ;
        var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
        var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
       //D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
        var W = I.x + I.y*71.0 + 125.0*I.z;
    
        return lerps(           
                    lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.y)
                    ,
                    lerps( lerps(rndng(W+125.0),rndng(W+126.0),D.x) , lerps(rndng(W+153.0),rndng(W+154.0),D.x) , D.y)
                    ,
                    D.z
                    );
    }
    
    function lnz2 ( vtx: Vector3 ): float//2d noise
    {   
        vtx= Vector3 ( Mathf.Abs(vtx.x) , Mathf.Abs(vtx.y) , Mathf.Abs(vtx.z) ) ;
        var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
        var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
        D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
        var W = I.x + I.y*71.0 + 125.0*I.z;
    
        return lerps(       
                    lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.z)
                    ,
                    lerps( rndng(W+125.0), rndng(W+126.0),D.x)
                    ,
                    D.z
                    );                  
    }
    

    【讨论】:

      猜你喜欢
      • 2014-05-21
      • 1970-01-01
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 2011-06-12
      • 2013-10-11
      相关资源
      最近更新 更多