Homogeneous participating Media

For this feature, I created a new Header file at medium.h.
homogeneous_medium.cpp implements these functions. I then created a new Integrator volpath.cpp.

Homogeneous Medium

To controll the medium, the user can set two variables: A Color3f sigmaA for the absorbtion and a Color3f sigmaS for the scattering.
For the Path-Tracer, we make the assumption, that the camera is not within the medium and that media don't intersect. Solid elements within the media are allowed. The implementation is based on path_mis.cpp.
If we are within the medium, we sample the free flight time:


                        if (medium) {
                            float t = medium->sampleFreePath(sampler->next1D());
                            if (t < its.t) {
                                // ...
                            }
                        }
                    

For bounces in the medium, we then sample the phase function and sample a random emitter.


                        Vector3f phase = medium->samplePhaseFunction(sampler->next2D());
            
                        const Emitter * e = scene->getRandomEmitter(sampler->next1D());
    
                        EmitterQueryRecord eqr = EmitterQueryRecord(_ray.o);
                        Color3f color_emitter = e->sample(eqr, sampler->next2D()) * float(scene->getLights().size());
                    

We then also need to consider the transmittance for these illuminations.


                        Color3f t_shadow(1.f);
                        Intersection its_sh;
                        bool in_medium = true;
                        while (true) {
                            if (scene->rayIntersect(eqr.shadowRay, its_sh)) {
                                if (its_sh.mesh->isMedium()) {
                                    if (in_medium) {
                                        t_shadow * its_sh.mesh->getMedium()->getTransmittance(its_sh.t);
                                    }
    
                                    in_medium = !in_medium;
                                    eqr.shadowRay.o = eqr.shadowRay.o + eqr.shadowRay.d*its_sh.t;
                                }
                                color_emitter = 0.0f;
                                break;
                            }
                            break;
                        }
                    

Finally, we can create the next ray, set the throughput depending in the albedo of the medium and add everything to the complete illumination.


                        _ray = Ray3f(_ray.o + _ray.d*t, phase, 0, INFINITY);
                        throughput *= medium->getAlbedo();
                        sampledColor += throughput * 1/4.f*INV_PI* color_emitter * t_shadow;
                    

Validation

To validate the implementation, I created equal scenes for Mitsuba and compared the results.

Mitsuba Mine

                                
                            
Mitsuba Mine

                                
                            
Mitsuba Mine