I am implementing a pathtracer with both indirect and direct light sampling at each intersection (I believe the "direct light sampling" part is also referred to as "next event estimation"). I am trying to compute both direct-diffuse and direct-specular contributions of the light sources.

For that, I use a normalized Phong BRDF (formula taken from here), in which the contribution of each light source at an intersection is defined as (pseudo-code) :

directLighting = diffuse() + specular() / (intersection.location - light.location).lengthSquared();

diffuse() {
    normalization = 1.0f / PI;
    return material.metal ? Color::BLACK :
                            lightDotN * lightIntensity * lightColor * material.albedo * normalization;

specular() {
    if (observerDotReflected <= 0.0f) {
        return Color::BLACK;

    normalization = (material.smoothness + 1.0f) / (2.0f * PI);
    return (observerDotReflected ^ material.smoothness) * lightIntensity * lightColor *
           (material.metal ? material.albedo : material.specularity) * normalization;

This works well as long as I have pretty rough objects in my scene (below, a rough metallic sphere with smoothness = 25.0f, and a rough diffuse sphere with smoothness = 2.0f). clean

However, as soon as I introduce a very smooth and reflective object (below, a metallic sphere with smoothness = 10'000.0f), two problems appear : the specular lobe on the sphere is very ugly (we can see the individual points that resulted in non-zero specular contribution), and hot pixels/fireflies appear everywhere in the scene. fireflies

I think I understand why these exist : when the smoothness is high, the specular Phong BRDF returns ~0 almost all the time (when observerDotReflected is not very close to 1), but sometimes returns extremely bright values, which cause fireflies at other points in the scene when they are the result of an indirect bounce.

Note that the same effect appears whether I use point lights, or sphere lights (with a non-zero volume that I randomly sample).

Is there a conventional way to solve this problem ? I have seen this answer where the author indicates that for mirror-like specular surfaces (i.e. smoothness -> infinity), you should not directly sample specular lighting, but rather rely on indirect bounces intersecting light objects. Is this the only way to go about direct specular lighting ? Are there other solutions to this variance problem ?

  • $\begingroup$ What about multiple importance sampling (MIS)? $\endgroup$
    – Hubble
    Commented Apr 26, 2021 at 1:41
  • $\begingroup$ @Hubble I have read about MIS a few times in posts and articles, but it seemed like a very complicated and elaborate thing for me at the time. Do you by any chance have links to good resources for learning about it and implementing it ? $\endgroup$
    – Ewaren
    Commented Apr 26, 2021 at 9:58
  • 1
    $\begingroup$ You can look at Section 13.10.1 of PBRT. It's usually not too difficult to implement once you have a sampling strategy for your emitter and BRDF. $\endgroup$
    – Hubble
    Commented Apr 26, 2021 at 14:12
  • $\begingroup$ Thank you for the guidance. I have resorted to only computing direct-diffuse contributions for now, and handling specular contributions solely via indirect bounces, and it seems to work pretty well. I am having trouble sampling sphere lights and normalizing them properly however, but I will create another question for that. $\endgroup$
    – Ewaren
    Commented Apr 26, 2021 at 15:43
  • $\begingroup$ You could look into post-processing effects like median-filter to get rid of this noise. However do remember that this is just for displaying. research.dreamworks.com/wp-content/uploads/2018/08/… $\endgroup$ Commented Apr 27, 2021 at 0:48


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.