【发布时间】:2013-08-15 21:14:35
【问题描述】:
我正在研究一些用于相干噪声的各种实现(我知道有一些库,但这主要是为了我自己的启发和好奇心)以及如何使用它,我对原始版本有一个问题柏林噪音的事情。
根据this frequently linked Math FAQ,输出范围将在-1 和1 之间,但我不明白该值是如何在该范围内的。
据我了解,算法基本上是这样的:每个网格点都有一个关联的随机梯度向量,长度为1。然后,对于每个点,对于所有四个周围的网格点,计算随机梯度和从该网格点出发的向量的点积。然后,您使用精美的缓动曲线和线性插值将其降低到一个值。
但是,这是我的问题:这些点积有时会超出[-1, 1] 的范围,并且由于您最终在点积之间进行线性插值,这并不意味着最终值将,有时会超出[-1, 1]的范围?
例如,假设其中一个随机向量是 (sqrt(2)/2, sqrt(2)/2)(长度为 1)和 (0.8, 0.8)(在单位平方中),您得到的结果大致为 1.131。如果在线性插值中使用该值,则生成的值完全有可能大于1。而且,确实,在我的直接实施中,这种情况经常发生。
我错过了什么吗?
作为参考,这是我的 Java 代码。 Vec 是一个简单的类,用于执行简单的 2d 矢量算术,fade() 是缓动曲线,lerp() 是线性插值,gradient(x, y) 以Vec 为您提供该网格点的梯度。 gridSize 变量以像素为单位为您提供网格的大小(它的类型为 double):
public double getPoint(int x, int y) {
Vec p = new Vec(x / gridSize, y / gridSize);
Vec d = new Vec(Math.floor(p.x), Math.floor(p.y));
int x0 = (int)d.x,
y0 = (int)d.x;
double d00 = gradient(x0 , y0 ).dot(p.sub(x0 , y0 )),
d01 = gradient(x0 , y0 + 1).dot(p.sub(x0 , y0 + 1)),
d10 = gradient(x0 + 1, y0 ).dot(p.sub(x0 + 1, y0 )),
d11 = gradient(x0 + 1, y0 + 1).dot(p.sub(x0 + 1, y0 + 1));
double fadeX = fade(p.x - d.x),
fadeY = fade(p.y - d.y);
double i1 = lerp(fadeX, d00, d10),
i2 = lerp(fadeX, d01, d11);
return lerp(fadeY, i1, i2);
}
编辑:这是生成随机渐变的代码:
double theta = gen.nextDouble() * 2 * Math.PI;
gradients[i] = new Vec(Math.cos(theta), Math.sin(theta));
其中gen 是java.util.Random。
【问题讨论】:
标签: java perlin-noise