Exemple #1
0
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;

        //check if the ray intersects the scene
        if (!scene->rayIntersect(ray, its)) {
            //check if a distant disk light is set
            const Emitter* distantsDisk = scene->getDistantEmitter();
            if(distantsDisk == nullptr ) return Color3f(0.0f);

            //sample the distant disk light
            return distantsDisk->sampleL(ray.d);
        }

        //get the radiance of hitten object
        Color3f Le(0.0f, 0.0f, 0.0f);
        if (its.mesh->isEmitter()  ) {
            const Emitter* areaLightEM = its.mesh->getEmitter();
            const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
            Le = aEM->sampleL(-ray.d, its.shFrame.n, its);
        }

        //get the asigned BSDF
        const BSDF* curBSDF = its.mesh->getBSDF();

        Color3f Ld(0.0f, 0.0f, 0.0f);
        Color3f f(0.0f, 0.0f, 0.0f);
        Color3f totalLight(0.0f, 0.0f, 0.0f);

        //transform to the local frame
        //create a BRDF Query
        BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-ray.d), Vector3f(0.0f), EMeasure::ESolidAngle);

        //sample the BRDF
        Color3f mats =  curBSDF->sample(query, sampler->next2D());

        if(mats.maxCoeff() > 0.0f) {
            //Check for the light source
            Vector3f wo = its.toWorld(query.wo);
            Ray3f shadowRay(its.p, wo);
            Intersection itsShadow;
            if (scene->rayIntersect(shadowRay, itsShadow)) {
                //intersection check if mesh is emitter
                if(itsShadow.mesh->isEmitter()){
                    Ld = itsShadow.mesh->getEmitter()->radiance();
                }
            } else {
                //check for distant disk light
                const Emitter* distantsDisk = scene->getDistantEmitter();
                if(distantsDisk != nullptr ) Ld = distantsDisk->sampleL(wo);
            }

            totalLight += Ld * mats;
        }

        return Le + totalLight;
    }
Exemple #2
0
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;

        //check if the ray intersects the scene
        if (!scene->rayIntersect(ray, its)) {
            //check if a distant disk light is set
            const Emitter* distantsDisk = scene->getDistantEmitter();
            if(distantsDisk == nullptr ) return Color3f(0.0f);

            //sample the distant disk light
            Vector3f d = ray.d;
            return distantsDisk->sampleL(d);
        }

        //get the Number of lights from the scene
        const  std::vector<Emitter *> lights = scene->getEmitters();
        uint32_t nLights = lights.size();

        Color3f tp(1.0f, 1.0f, 1.0f);
        Color3f L(0.0f, 0.0f, 0.0f);
        Ray3f pathRay(ray.o, ray.d);

        bool deltaFlag = true;

        while(true) {

            if (its.mesh->isEmitter() && deltaFlag) {
                const Emitter* areaLightEM = its.mesh->getEmitter();
                const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
                L += tp * aEM->sampleL(-pathRay.d, its.shFrame.n, its);
            }

            //Light sampling
            //randomly select a lightsource
            uint32_t var = uint32_t(std::min(sampler->next1D()*nLights, float(nLights) - 1.0f));

            //init the light color
            Color3f Li(0.0f, 0.0f, 0.0f);
            Color3f Ld(1.0f, 1.0f, 1.0f);

            //create a sample for the light
            const BSDF* curBSDF = its.mesh->getBSDF();
            const Point2f lightSample = sampler->next2D();
            VisibilityTester vis;
            Vector3f wo;
            float lightpdf;
            float bsdfpdf;
            Normal3f n = its.shFrame.n;

            deltaFlag = curBSDF->isDeltaBSDF();

            //sample the light

            {
                Li = lights[var]->sampleL(its.p, Epsilon, lightSample , &wo, &lightpdf, &vis);
                lightpdf /= float(nLights);
                //check if the pdf of the sample is greater than 0 and if the color is not black
                if(lightpdf > 0 && Li.maxCoeff() != 0.0f) {
                    //calculate the cosine term wi in my case the vector to the light
                    float cosTerm = std::abs(n.dot(wo));
                    const BSDFQueryRecord queryEM = BSDFQueryRecord(its.toLocal(- pathRay.d), its.toLocal(wo), EMeasure::ESolidAngle, sampler);
                    Color3f f = curBSDF->eval(queryEM);

                    if(f.maxCoeff() > 0.0f && f.minCoeff() >= 0.0f && vis.Unoccluded(scene)) {
                        bsdfpdf = curBSDF->pdf(queryEM);
                        float weight = BalanceHeuristic(float(1), lightpdf, float(1), bsdfpdf);
                        if(curBSDF->isDeltaBSDF())  weight = 1.0f;
                        if(bsdfpdf > 0.0f) {
                            Ld = (weight * f * Li * cosTerm) / lightpdf;
                            L += tp * Ld;
                        } else {
                            //cout << "bsdfpdf = " << bsdfpdf  << endl;
                            //cout << "f = " << f  << endl;
                        }
                    }
                }
            }

            //Material part
            BSDFQueryRecord queryMats = BSDFQueryRecord(its.toLocal(-pathRay.d), Vector3f(0.0f), EMeasure::ESolidAngle, sampler);

            Color3f fi =  curBSDF->sample(queryMats, sampler->next2D());
            bsdfpdf = curBSDF->pdf(queryMats);
            lightpdf = 0.0f;
            if(fi.maxCoeff() > 0.0f && fi.minCoeff() >= 0.0f) {
                if(bsdfpdf > 0.0f) {
                    Ray3f shadowRay(its.p, its.toWorld(queryMats.wo));
                    Intersection lightIsect;

                     if (scene->rayIntersect(shadowRay, lightIsect)) {
                         if(lightIsect.mesh->isEmitter()){
                            const Emitter* areaLightEMcur = lightIsect.mesh->getEmitter();
                            const areaLight* aEMcur = static_cast<const areaLight *> (areaLightEMcur);

                            Li = aEMcur->sampleL(-shadowRay.d, lightIsect.shFrame.n, lightIsect);
                            lightpdf = aEMcur->pdf(its.p, (lightIsect.p - its.p).normalized(), lightIsect.p, Normal3f(lightIsect.shFrame.n));
                         }
                     } else {
                         const Emitter* distantsDisk = scene->getDistantEmitter();
                         if(distantsDisk != nullptr ) {
                             //check if THIS is right!
                             Li = distantsDisk->sampleL(lightIsect.toWorld(queryMats.wo));
                             lightpdf = distantsDisk->pdf(Point3f(0.0f), wo, Point3f(0.0f), Normal3f(0.0f));
                         }
                     }
                     lightpdf /= float(nLights);
                     //calculate the weights
                     float weight = BalanceHeuristic(float(1), bsdfpdf, float(1), lightpdf);


                     //check if the lightcolor is not black
                     if(Li.maxCoeff() > 0.0f  && lightpdf > 0.0f ) {
                         //wo in my case the vector to the light
                         Ld = weight * Li * fi;
                         L += tp * Ld;
                     }
                }



                 tp *= fi;
            } else {
                break;
            }

            wo = its.toWorld(queryMats.wo);
            pathRay = Ray3f(its.p, wo);

            if (!scene->rayIntersect(pathRay, its)) {
                const Emitter* distantsDisk = scene->getDistantEmitter();
                if(distantsDisk != nullptr ) {
                    //sample the distant disk light
                    Vector3f d = pathRay.d;
                    L += tp * distantsDisk->sampleL(d);
                }


                break;
            }

            float maxCoeff = tp.maxCoeff();
            float q = std::min(0.99f, maxCoeff);
            if(q < sampler->next1D()){
                break;
            }
            tp /= q;
        }

        return L;

    }
Exemple #3
0
    void preprocess(const Scene *scene) {
        /* Create a sample generator for the preprocess step */
        Sampler *sampler = static_cast<Sampler *>(
            NoriObjectFactory::createInstance("independent", PropertyList()));

        Emitter* distantsDisk = scene->getDistantEmitter();
        if(distantsDisk != nullptr ) {
            float lngstDir = scene->getBoundingBox().getLongestDirection();
            distantsDisk->setMaxRadius(lngstDir);
        }

        /* Allocate memory for the photon map */
        m_photonMap = std::unique_ptr<PhotonMap>(new PhotonMap());
        m_photonMap->reserve(m_photonCount);

		/* Estimate a default photon radius */
		if (m_photonRadius == 0)
			m_photonRadius = scene->getBoundingBox().getExtents().norm() / 500.0f;

        int storedPhotons = 0;

        const  std::vector<Emitter *> lights = scene->getEmitters();
        int nLights = lights.size();
        Color3f tp(1.0f, 1.0f, 1.0f);

        cout << "Starting to create "<< m_photonCount << " photons!" << endl;
        int percentDone= 0;
        int onePercent = int(floor(m_photonCount / 100.0));

        // create the expected number of photons
        while(storedPhotons < m_photonCount) {
            //uniformly sample 1 light (assuming that we only have area lights)
            int var = int(std::min(sampler->next1D()*nLights, float(nLights) - 1.0f));
            const areaLight* curLight = static_cast<const areaLight *> (lights[var]);

            //sample a photon
            Photon curPhoton;
            Vector3f unQuantDir(0.0f,0.0f,0.0f);
            curLight->samplePhoton(sampler, curPhoton, 1, nLights, unQuantDir);
            Color3f alpha = curPhoton.getPower();
            Color3f tp(1.0f, 1.0f, 1.0f);


            //trace the photon
            Intersection its;
            Ray3f photonRay(curPhoton.getPosition(), unQuantDir);
            m_shootedRays++;
            if (scene->rayIntersect(photonRay, its)) {
                while(true) {
                    const BSDF* curBSDF = its.mesh->getBSDF();


                    if (curBSDF->isDiffuse()) {
                        //store the photon
                        m_photonMap->push_back(Photon(
                            its.p  /* Position */,
                            -photonRay.d /* Direction*/,
                            tp * alpha  /* Power */
                        ));
                        storedPhotons++;
                    }

                    if(!(storedPhotons < m_photonCount)) break;

                    BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-photonRay.d), Vector3f(0.0f), EMeasure::ESolidAngle);
                    Color3f fi =  curBSDF->sample(query, sampler->next2D());

                    if(fi.maxCoeff() == 0.0f) break;

                    tp *= fi;

                    Vector3f wo = its.toWorld(query.wo);
                    photonRay = Ray3f(its.p, wo);

                    //ray escapes the scene
                    if (!scene->rayIntersect(photonRay, its)) break;

                    //stop critirium russian roulette
                    float q = tp.maxCoeff();
                    if(q < sampler->next1D()) break;
                    tp /= q;
                }

            }
            if(onePercent != 0) {
                if(storedPhotons % onePercent == 0){
                    int percent = int(floor(storedPhotons / onePercent));
                    if(percent % 10 == 0 && percentDone != percent){
                        percentDone = percent;
                        cout << percent << "%" << endl;
                    }
                }
            }
        }

		/* Build the photon map */
        m_photonMap->build();
    }
Exemple #4
0
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;


        //check if the ray intersects the scene
        if (!scene->rayIntersect(ray, its)) {
            return Color3f(0.0f);
        }

        Color3f tp(1.0f, 1.0f, 1.0f);
        Color3f L(0.0f, 0.0f, 0.0f);
        Ray3f pathRay(ray.o, ray.d);
        while(true) {

            //get the radiance of hitten object

            if (its.mesh->isEmitter() ) {
                const Emitter* areaLightEM = its.mesh->getEmitter();
                const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
                L += tp * aEM->sampleL(-pathRay.d, its.shFrame.n, its);
            }

            //get the asigned BSDF
            const BSDF* curBSDF = its.mesh->getBSDF();

            //transform to the local frame
            BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-pathRay.d), Vector3f(0.0f), EMeasure::ESolidAngle);

            //Normal3f n = its.shFrame.n;



            if(curBSDF->isDiffuse()) {
                std::vector<uint32_t> results;
                m_photonMap->search(its.p, m_photonRadius, results);
                Color3f Li(0.0f, 0.0f, 0.0f);
                int k = results.size();
                //cout << k << endl;

                if(k > 0) {

                    //cout << results.size() << " Photons found!" << endl;
                    //get the power from all photons
                    //for (uint32_t i : results)
                    //const Photon &photonk = (*m_photonMap)[k-1];
                    Color3f Lindir(0.0f, 0.0f, 0.0f);
                    for (int i = 0; i < k; ++i)
                    {
                        const Photon &photon = (*m_photonMap)[results[i]];
                        Vector3f wi = its.toLocal(photon.getDirection());
                        Vector3f wo = its.toLocal(its.shFrame.n);
                        BSDFQueryRecord dummy = BSDFQueryRecord(wi, wo, EMeasure::ESolidAngle);
                        Color3f f = curBSDF->eval(dummy);


                        Lindir += (tp * f) * photon.getPower() / (M_PI * m_photonRadius * m_photonRadius);


                    }

                    Li += Lindir;

                    //cout << "Li = " <<  Li.toString() << endl;
                    if(Li.maxCoeff() > 0.0f)
                        L +=  Li  / m_shootedRays;

                }
                break;
            }

            //sample the BRDF
            Color3f fi =  curBSDF->sample(query, sampler->next2D());
            //check for black brdf
            if(fi.maxCoeff() > 0.0f) {
                tp *= fi;
            } else {
                //stop
                // hit a black brdf
                break;
            }
            Vector3f wo = its.toWorld(query.wo);
            pathRay = Ray3f(its.p, wo);

            //ray escapes the scene
            if (!scene->rayIntersect(pathRay, its)) break;


            //stop critirium russian roulette
            float maxCoeff = tp.maxCoeff();
            float q = std::min(0.99f, maxCoeff);
            if(q < sampler->next1D()) break;
            tp /= q;
        }
        return L;
    }