(L) [2012/04/18] [ost
by KaRaMBa] [Fireflies in pathtracer] Wayback!>> Dade wrote:KaRaMBa wrote: MIS reduces high variance noise in scenes with shiny surfaces, but would it also help in a completely diffuse scene like this?
Yup, it does, your fireflies are likely to be caused by paths directly hitting a very near light source. If you lower the light sources in your scene, you will see how the fireflies will disappear.
My path tracer takes a similar aproach for direct sampling of lights as the (extended) smallpt pathtracer:
- If a ray hits a diffuse surface, a random point on a random light is picked and a shadow ray is send. If the lightsource is visible, the appropriate amount of light is added
- Next, a random diffuse ray is send into the scene to add indirect lighting, and directly hitting lightsources is disabled
This gives nice noise-free results within very little samples, if the lightlevel is below 1.0. However, more intense lights are required to sufficently light the scene.
If I move the lightsource down, such that the bright area on te ceiling is less bright, my fireflies also reduce drasticly. I susspect a random diffuce ray hitting the very bright diffuse area above the lightsource, is the cause of my fireflies... (N.B. this is similar to the discussion on the second page of this topic: [LINK http://ompf2.com/viewtopic.php?f=3&t=5 viewtopic.php?f=3&t=5])
Since i disable the hitting of lightsources after a diffuse bounce, how would MIS solve this issue? As I understand, MIS only solves variance introduced by hitting lightsources with the an unlikely chance (which isn't possible in my case)? And if I didn't understand MIS correct, how would I implement MIS in my case (what probablilites should I mix)?
I've added a snipset (pseudocode) of my tracer:
Code: [LINK # Select all]COLOR pathTracer(const KDTREE *world, POINT *pt, POINT *dir)
{
    COLOR colscale = {1.0f, 1.0f, 1.0f};
    COLOR ret = {0.0f, 0.0f, 0.0f};
    int depth = 0, allowlight = 1;
    while(1)
    {
        if(depth>15) break;
        
        IXPT *ixpt = findIntersectPt(world, pt, dir);        // Intersection point ixpt contains information about hit: face, hitpoint, etc
        
        if(!ixpt)    // nothing hit, add sky-light
        {
            ret += skyColor(dir) * colscale;
            return ret;
        }
        POINT norm = getFaceNormalAtPoint(ixpt);
        if(ixpt->face.emit)
        {
            if(allowlight)
                ret += ixpt->face.color * colscale * ixpt->face.emit;
            return ret;
        }
        else // diffuse hit
        {
            // Directly sample light
            POINT newdir;
            COLOR lightColor;
            const tReal pdf = sampleLight(dir, ixpt->pt, &norm, &newdir, &lightColor);
            const tReal brdf = brdf_Lambert(dir, ixpt->pt, &norm, &newdir);
            const tReal scale = brdf / pdf;
            if(!findObscured(world, &ixpt->pt, &newdir))
                ret += ixpt->face.color * lightColor * colscale * scale;
            allowlight = 0;    // directly sampled lights, so exclude them from being hit accidentally
            // Now do a diffuce bounce for indirect lightning
            static const tReal Prr = 0.9;
            if(sample()<Prr)
            {
                const tReal pdf = sampleVectorCosweighted(dir, ixpt->pt, &norm, &newdir);
                const tReal brdf = brdf_Lambert(dir, ixpt->pt, &norm, &newdir);
                const tReal scale = brdf / (pdf * Prr);
                if(scale > REL_EPSYLON)
                {
                    colscale *= matcol * scale;
                    *pt = ixpt->pt;
                    *dir = newdir;
                    depth++;
    
                    continue;
                }
            }
            return ret;
        }
    }
}