Search code examples
renderingshadowshapesraytracinglight

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


I'm trying to implement different types of lights in my ray-tracer coded in C. I have successfully implemented spot, point, directional and rectangular area lights.

For rectangular area light I define two vectors (U and V) in space and I use them to move into the virtual (delimited) rectangle they form. Depending on the intensity of the light I take several samples on the rectangle then I calculate the amount of the light reaching a point as though each sample were a single spot light. rectangular light samples

With rectangles it is very easy to find the position of the various samples, but things get complicated when I try to do the same with a disk light. I found little documentation about that and most of them already use ready-made functions to do so. The only interesting thing I found is this document (https://graphics.pixar.com/library/DiskLightSampling/paper.pdf) but I'm unable to exploit it.

Would you know how to help me achieve a similar result (of the following image) with vector operations? (ex. Having the origin, orientation, radius of the disk and the number of samples) Disk light samples

Any advice or documentation in this regard would help me a lot.


Solution

  • This question reduces to:

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

    A naive approach would be to generate random polar coordinates and transform them to cartesian coordinates:

    1. Randomly generate an angle θ between 0 and
    2. Randomly generate a distance d between 0 and radius r of your disk
    3. Transform to cartesian coordinates with x = r cos θ and y = r sin θ

    This is incorrect because it causes the points to bunch up in the center; for example:

    Incorrect uniform disk sampling

    A correct, but inefficient, way to do this is via rejection sampling:

    1. Uniformly generate random x and y, each over [0, 1]
    2. If sqrt(x^2 + y^2) < 1, return the point
    3. Goto 1

    disk rejection sampling

    The correct way to do this is illustrated here:

    1. Randomly generate an angle θ between 0 and
    2. Randomly generate a distance d between 0 and radius r of your disk
    3. Transform to cartesian coordinates with x = sqrt(r) cos θ and y = sqrt(r) sin θ