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.
