Sampling, Antialiasing, and Monte Carlo

Sampling, Antialiasing, and Monte Carlo

One sample through the pixel center produces a recognizable image and a bad final image. Edges stair-step. Thin highlights alias. High-frequency texture detail sparkles under motion.

The first remedy is not a blur filter. The first remedy is correct sampling and averaging in linear space.

Stratified samples inside a pixel versus one center sample

Several stratified samples inside a pixel beat one center sample near edges.

Pixel antialiasing

color = 0
for k = 1..N:
    (s, t) = stratified or random in [0, 1)²
    ray = camera.generate(i, j, s, t)
    color += trace(ray)
color /= N

Stratified sampling partitions the pixel into cells and places one sample in each cell. It reduces clumping relative to pure white noise. Blue-noise tables are better for stills when available. Stratification is enough while you learn.

Monte Carlo estimation

To approximate an integral, sample the domain and average carefully:

∫ f(x) dx  ≈  (1/N) Σ f(x_i) / p(x_i)

Here p is the probability density that generated x_i. Forget the PDF and image brightness becomes a function of your sampling strategy. That bug is easy to ship and hard to notice if you only stare at relative contrast.

Light sampling and BSDF sampling

Direct lighting can sample lights. Indirect lighting often samples the BSDF. Ideal mirrors must be sampled by their reflection direction. Random hemisphere directions will almost never hit a Dirac lobe.

A practical teaching order:

  1. stratified pixel samples
  2. one analytic light with shadow rays
  3. cosine-weighted hemisphere samples for diffuse indirect light
  4. multiple importance sampling only after the above are correct

Cosine-weighted hemisphere

Uniform hemisphere sampling wastes effort near the horizon, where cosθ kills the contribution. For Lambertian surfaces, cosine-weighted sampling matches the integrand better:

r1, r2 ~ U(0,1)
φ = 2π r1
r = sqrt(r2)
x = r cosφ
y = r sinφ
z = sqrt(max(0, 1 - r2))
pdf = z / π

Transform (x,y,z) into world space with a basis around n. For Lambert, f cosθ / pdf simplifies cleanly. If the simplified result disagrees with brute-force evaluation, the sampler is wrong.

Noise versus bias

Too few samples produce noise. A missing PDF term or an energy clamp produces bias. Denoisers hide noise. They cannot invent the correct mean of a wrong estimator. Prefer a noisy correct image while debugging.

Temporal behavior

Still frames conceal crawling edges. Camera motion reveals them. Per-frame white noise shimmers. Stable sequences are a later topic. Honesty of the still estimator comes first.

Common errors

  • Randomizing only one pixel axis
  • Averaging sRGB values instead of linear values
  • Hemisphere samples without the matching PDF
  • Using 1/N while forgetting 1/pdf
  • Enabling a denoiser before high-sample raw accumulation is trustworthy

If increasing sample count lowers noise without shifting average brightness, the estimator is probably sane.

Expected value intuition

If each sample is an unbiased estimate of pixel radiance, the average of N samples is also unbiased and its variance falls roughly like 1/N for independent samples. That is why four times the samples halves the RMS noise only in the independent case, and why structured samplers can look better sooner. You are estimating an integral. You are not “drawing harder.”

Domain checklist

State the domain before coding a sampler:

  • pixel area
  • lens disk
  • light area
  • hemisphere around n
  • time interval

Each domain has a measure and a PDF. If you cannot write the PDF, you are not finished designing the sampler.