是否有一个简单的数学解决方案来对磁盘区域光进行采样? (光线追踪)

Is there a simple math solution to sample a disk area light? (Raytracing)

我正在尝试在用 C 编码的光线追踪器中实现不同类型的灯光。我已经成功地实现了聚光灯、点灯、定向灯和 矩形区域 灯。

对于 矩形区域光 我在 space 中定义了两个向量(U 和 V),我使用它们移动到它们形成的虚拟(分隔)矩形中。 根据光的强度,我在矩形上取了几个样本,然后计算到达一个点的光量,就好像每个样本都是一个聚光灯一样。

使用矩形很容易找到各种样本的位置,但是当我尝试用 圆盘灯 做同样的事情时,事情就变得复杂了。 我发现很少有关于它的文档,而且它们中的大多数已经使用现成的函数来做到这一点。 我发现的唯一有趣的事情是这个文档 (https://graphics.pixar.com/library/DiskLightSampling/paper.pdf),但我无法利用它。

你知道如何用矢量运算帮助我获得类似的结果(下图)吗? (例如,具有圆盘的原点、方向、半径和样本数)

这方面的任何建议或文档都会对我有很大帮助。

这个问题简化为:

How can I pick a uniformly-distributed random point on a disk?

一种天真的方法是随机生成 polar coordinates 并将它们转换为笛卡尔坐标:

  1. 0之间随机生成一个角度θ
  2. 0 和您的磁盘半径 r 之间随机生成一个距离 d
  3. 使用 x = r cos θy = r sin θ
  4. 转换为笛卡尔坐标

这是不正确的,因为它会导致点在中心聚集;例如:

一种正确但低效的方法是通过 rejection sampling:

  1. 均匀生成随机xy,每个超过[0, 1]
  2. 如果sqrt(x^2 + y^2) < 1,return点
  3. 转到 1

说明了正确的方法 here:

  1. 0之间随机生成一个角度θ
  2. 0 和您的磁盘半径 r 之间随机生成一个距离 d
  3. 使用 x = sqrt(r) cos θy = sqrt(r) sin θ
  4. 转换为笛卡尔坐标