10

我需要澄清一下为我的宠物光线追踪器生成随机值的算法。
我从一点发射光线。我对这些光线的分布有疑问:我需要分布均匀,但不是......

我现在面临的问题是,在我扭曲了结果空间之后,最初均匀的分布并不均匀。

例如,如果是极坐标系,我会生成 r 和 t 角。分布不均匀,也不可能是均匀的:靠近每个极点的空间比靠近赤道的空间具有更多的结果密度。原因很清楚:我将均匀分布的点从圆柱形空间转换为球形。我扭曲了结果。同样的问题是,如果我对多维数据集中随机生成的点进行归一化。

我现在的想法是:我想创建一个四面体,标准化它的顶点,用中间的点分割每个面(三角形),标准化它并递归重复,直到我有足够的点。然后我稍微“扭曲”这些观点。然后我再次标准化它们。而已。

我知道这种方法本身并不是纯数学的蒙特卡罗方法,因为除了最后一步之外,我在任何步骤中都没有使用随机分布。而且我不喜欢这种复杂性的解决方案。

任何人都可以提出更简单的建议吗

  • 随机的
  • 制服
  • 快速地
  • 简单的

谢谢!

编辑:
我需要一种快速的方法,而不仅仅是正确的方法。这就是我问蒙特卡洛的原因。提供的答案是正确的,但不是很快。四面体的方法很快,但不是很“随机”=>不正确。
我真的需要更合适的东西。

4

5 回答 5

10

这是一种算法,可让您生成随机分布在单位球面上的点。

于 2009-12-03T16:29:57.670 回答
5

这是我过去使用过的 Java 实现:

public static double[] randomPointOnSphere(Random rnd)
{
    double x, y, z, d2;
    do {
        x = rnd.nextGaussian();
        y = rnd.nextGaussian();
        z = rnd.nextGaussian();
        d2 = x*x + y*y + z*z;
    } while (d2 <= Double.MIN_NORMAL);
    double s = Math.sqrt(1.0 / d2);
    return new double[] {x*s, y*s, z*s};
}
于 2011-01-24T16:33:34.580 回答
4

你真的需要随机分布还是球体上的均匀分布?

然后我会建议 ZCW 角度,它在整个球体上均匀分布并且计算速度很快。其他方法是悉尼歌剧院 (SOPHE) 和排斥。(搜索repulsion.c)排斥方法非常好,但速度很慢:它迭代地将点均匀地分布在一个球体上。幸运的是,它只需要执行一次。

这用于晶体学和 NMR,因为对于粉末图案,使用均匀分布比随机分布更快(您需要更少的点)。

是 ZCW 的 Python 实现。

这些论文中的更多详细信息:

于 2011-10-31T10:04:11.267 回答
2

除非您只对微不足道的场景进行光线追踪,否则您的渲染时间真的会受到采样时间的支配吗?如果没有,它可能还不值得优化,尽管值得阅读和理解其他答案中给出的统一采样技术。

此外,您的样本不需要非常随机,以便对您正在采样的任何函数产生良好的估计。您可能希望使用准随机数序列(例如Halton 序列)进行调查。你的四面体细分想法还不错。它应该会产生分布良好的点,对于大多数场景来说应该比均匀的伪随机样本更好,尽管在某些情况下可能会导致可怕的伪影。

无论如何,您确实应该咨询 ompf.org 上的论坛。那里有一些超级铁杆光线追踪书呆子。

于 2009-12-05T08:52:36.533 回答
2

对于球面部分,您的角度在phi(极角)和cos(theta)(对于 theta 方位角)在您的极限之间均匀生成。

在伪代码中:

phi = phi_low_limit        + rand()*(phi_high_limit       - phi_low_limit)
ct = cos(theta_high_limit) + rand()*(cos(theta_low_limit) - cos(theta_high_limit))
// The order is inverted here because cos heads down for increasing theta
theta = arccos(ct)

这是规则的一个特例,即反转雅可比并在这些坐标的空间中均匀生成。

注意:请注意,我使用与 David Norman 行相反的 phi 和 theta 约定。

另请注意:这实际上并不是最快的方法,而是说明一般原则的方法。

于 2009-12-03T17:33:00.407 回答