柏林噪音重复模式

时间:2018-03-29 17:35:05

标签: java algorithm perlin-noise

我的问题是我的perlin噪音在非常小的空间中非常明显地重复。 Here is an image of what it going on.我知道这确实发生在所有perlin噪音的某个点之后,但它似乎几乎立即发生在我的身上。我相信它是由我非常糟糕的伪随机梯度生成器引起的,但我不确定。我的代码如下。

enter image description here

作为旁注,我的perlin噪声似乎产生非常小的值,介于-.2和正.2之间,我认为这也是由我的伪随机梯度生成器引起的。

如果有人对改进我的代码部分有任何建议,请随时告诉我。任何想法现在都会有所帮助。

提前感谢大家!

public class Perlin {
    int[] p = new int[255];
    public Perlin() {
        for(int i = 0; i < p.length; i++)
            p[i] = i;

        shuffle(p);
    }

    int grads[][] = {
            {1,0},{0,1},{-1,0},{0,-1},
            {1,1},{-1,1},{1,-1},{-1,-1}
    };

    public double perlin (double x, double y) {

        int unitX = (int)Math.floor(x) & 255; // decide unit square
        int unitY = (int)Math.floor(y) & 255; // decide unit square

        double relX = x-Math.floor(x); // relative x position
        double relY = y-Math.floor(y); // relative y position

        // bad pseudorandom gradient -- what i think is causing the problems
        int units = unitX+unitY;
        int[] gradTL = grads[p[(units)]%(grads.length)];
        int[] gradTR = grads[p[(units+1)]%(grads.length)];
        int[] gradBL = grads[p[(units+1)]%(grads.length)];
        int[] gradBR = grads[p[(units+2)]%(grads.length)];

        // distance from edges to point, relative x and y inside the unit square
        double[] vecTL = {relX,relY};
        double[] vecTR = {relX-1,relY};
        double[] vecBL = {relX,relY-1};
        double[] vecBR = {relX-1,relY-1};

        // dot product
        double tl = dot(gradTL,vecTL);
        double tr = dot(gradTR,vecTR);
        double bl = dot(gradBL,vecBL);
        double br = dot(gradBR,vecBR);

        // perlins fade curve
        double u = fade(relX);
        double v = fade(relY);

        // lerping the faded values
        double x1 = lerp(tl,tr,u);
        double y1 = lerp(bl,br,u);

        // ditto
        return lerp(x1,y1,v);
    }
    public double dot(int[] grad, double[] dist) {
        return (grad[0]*dist[0]) + (grad[1]*dist[1]);
    }
    public double lerp(double start, double end, double rate){
        return start+rate*(end-start);
    }
    public double fade(double t) {
        return t*t*t*(t*(t*6-15)+10);
    }
    public void shuffle(int[] p) {
        Random r = new Random();
        for(int i = 0; i < p.length; i++) {
            int n = r.nextInt(p.length - i);
            // do swap thing
            int place = p[i];
            p[i] = p[i+n];
            p[i+n] = place;
        }
    }
}

关于我的渐变生成器的旁注,我知道Ken Perlin使用了255,因为他正在使用位,我只是随机选择它。如果它被改变,我认为它对模式没有任何影响。

1 个答案:

答案 0 :(得分:0)

您的直觉是正确的。您计算:

int units = unitX+unitY;

,然后将其用作所有渐变表查找的基础。这样可以保证您在坡度为-1的线上获得相同的值,这正是我们假设(0,0)是左上角的情况。

我建议使用一个真正的哈希函数来组合您的坐标:xxHash,Murmur3甚至是像CRC32这样的东西(这并不意味着是哈希)会比您正在做的事情要好得多。您还可以实现Perlin的原始哈希函数,尽管它具有各向异性的已知问题。