예제 #1
0
        public Spectrum Li(Ray r, Scene s)
        {
            /* BASIC Implement
            repeat
                r <- random ray from camera
                L <- 0, β <- 1, nbounces <- 0
                repeat
                   isect <- intersect r with scene
                   if isect == null // no hit
                      break
                   wo <- -r
                   if isect == light // light hit
                      L<- β*Le(wo) // add light emitted
                      break
                   wi <- random ray from isect
                   (f,pr) <- bsdf(isect,wi,wo)
                   β <- β*f*|cosθ|/pr
                   r <- wi
                   nbounces <- nbounces+1
                AddSampleToImage(L,r)
            */


            /* Russian Roulette Implement

            (f,pr) <- bsdf(isect,wi,wo)
            β <- β*f*|cosθ|/pr
            r <- wi
            if nbounces>3
            q <- 1 - max(β)
            if random() < q
            break
            β <- β/(1-q)

             */
            var L = Spectrum.ZeroSpectrum;
            var beta = Spectrum.Create((double)1);
            int nbounces = 0;
            double q;

            while(nbounces < 20) {
                (double? mint, SurfaceInteraction si) = s.Intersect(r);

                // If nothing hit end
                if (si == null) {
                    break;
                }

                // If Light hit include it and finish
                if (si.Obj is Light) {
                    if (nbounces == 0)
                    {
                        L = beta * si.Le(si.Wo);
                        //Console.WriteLine(beta.c);
                        //Console.WriteLine(L.c);
                    }
                    break;
                }

                // Sample light from SurfaceInteraction
                // TODO
                Spectrum Ld = Light.UniformSampleOneLight(si, s);

                L = L.AddTo(beta * Ld);
                
                // Make new reflected Ray
                //Ray wi = si.SpawnRay(UniformSampleSphere());
                
                // Get BSDF of hit object
                (Spectrum f, Vector3 wi, double pr, bool p) = (si.Obj as Shape).BSDF.Sample_f(si.Wo, si);

                // Update beta
                beta = beta * f * Utils.AbsCosTheta(wi) / pr;
                // Set reflected Ray as original Ray
                r = new Ray(si.Point, wi);

                if (nbounces > 3) {
                    q = 1 - beta.Max();
                    if (ThreadSafeRandom.NextDouble() < q) {
                        break;
                    }
                    beta /= (1 - q);
                }

                nbounces += 1;
            }
            Console.WriteLine(L.c);
            return L;
        }