In my ray tracter on sharp edges like the rim of the spheres a strong aliasing effect can be seen, so I decided to look at antialising this time.

Randomizing sub-pixel positions

So far I have been initiating rays from the centers of pixels always, instead of that I can simply generate two uniform random numbers on [0,1] and initiate a ray from that sub-pixel position.

I introduced a new enum, expecting having to add different strategies for sampling:

enum class PixelSampling : int {
    Center = 0,
    UniformRandom = 1,
};

Then in the camera ray sampling I pass in the chosen pixel sampling, sample index and random number generator:

template<typename Rng>
Ray cameraRay(
    const Camera &cam, Vec2f pixelCoord, 
    PixelSampling sampling, int index, Rng &rng
);

Then choosing the subpixel position:

Ray cameraRay(...)
{
    Vec2f subPixelCoord;

    if (sampling == PixelSampling::Center) {
        subPixelCoord = Vec2{0.5, 0.5};
    }
    if (sampling == PixelSampling::UniformRandom) {
        subPixelCoord = Vec2{rng.rnd(), rng.rnd()};
    }

    // ... Generate ray as before
}

This resulted in pretty nice antialising on the blue ball:

Also enhances the glass balls, where a small displacement changes the ray’s path drastically. Notice how the highlights are not pixelated anymore:

Later work?

Choosing pixel sampling in a uniform random manner is suboptimal. Using a low discrepancy deterministic sequence such as The Halton Sequence should result in faster reduction of more samples are drawn.

However, I found that in this scene the random sampling produced pretty nice results already fast enough. So I made the choice of not diving into alternatives right now.

I will return to adding more sampling methods as needed.

Bonus image of the debugging view:

The anti-aliasing effect is especially visible along the edges again.