【问题标题】:Perlin Noise repeating patternPerlin 噪声重复模式
【发布时间】:2018-03-29 17:35:04
【问题描述】:

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

附带说明一下,我的 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,因为他使用的是位,我只是随机选择了它。我认为如果改变它对模式没有任何影响。

【问题讨论】:

  • "Perlin 用的是 255,因为他用的是比特,我只是随便挑的"...你应该先实现原始算法,然后修改它。
  • 我有一个非常简单的算法版本,它不是最高效也不是最复杂的,但它仍然是原始算法。
  • “我认为如果改变它对模式没有任何影响” - 那么你在猜测。验证很容易,您应该这样做。此外,您可以选择将种子传递给构造函数以初始化 RNG。如果不这样做,您将永远无法重现特定的问题案例,也无法确定您是否真的修复了它们。
  • 我检查并切换了 p[] 的长度,但没有任何改变。另外,这不是一个特定的问题案例,每次运行程序时都会出现这样的模式。

标签: java algorithm perlin-noise


【解决方案1】:

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

int units = unitX+unitY;

然后将其用作所有梯度表查找的基础。这保证了沿着斜率 -1 的线得到相同的值,这正是我们假设 (0, 0) 是左上角所看到的。

我建议使用真正的散列函数来组合您的坐标:xxHash、Murmur3 甚至 CRC32 之类的东西(这并不意味着是散列)会比您正在做的要好得多。您也可以实现 Perlin 的原始哈希函数,尽管它存在各向异性问题。

【讨论】:

    猜你喜欢
    • 2014-02-15
    • 2020-06-06
    • 2011-09-20
    • 2021-06-30
    • 2013-07-23
    • 2020-06-22
    • 2011-03-19
    • 1970-01-01
    • 2014-05-21
    相关资源
    最近更新 更多