Exemple #1
0
        public override Spectrum f(Vector3 wo, Vector3 wi)
        {
            double a = 1 - ((roughness2 / 2 * (roughness2 + 0.33)));
            double b = 0.45 * roughness2 / (roughness2 + 0.09);

            double sinThetaI = Utils.SinTheta(wi);
            double sinThetaO = Utils.SinTheta(wo);

            double sinAlpha;
            double tanBeta;

            if (Utils.AbsCosTheta(wi) > Utils.AbsCosTheta(wo))
            {
                sinAlpha = sinThetaO;
                tanBeta  = sinThetaI / Utils.AbsCosTheta(wi);
            }
            else
            {
                sinAlpha = sinThetaI;
                tanBeta  = sinThetaO / Utils.AbsCosTheta(wo);
            }
            double maxCos = 0;

            if (sinThetaI > 1e-4 && sinThetaO > 1e-4)
            {
                double dCos = Utils.CosPhi(wi) * Utils.CosPhi(wo) + Utils.SinPhi(wi) * Utils.SinPhi(wo);
                maxCos = Math.Max(0, dCos);
            }

            Spectrum nnn = (kd / Math.PI) * (a + b * maxCos * sinAlpha * tanBeta);

            return(nnn);
        }
Exemple #2
0
        public override Spectrum f(Vector3 wo, Vector3 wi)
        {
            if (!Utils.SameHemisphere(wo, wi))
            {
                return(Spectrum.ZeroSpectrum);
            }

            // Cos term
            // Adicijski izrek: cos(x +- y) = cos(x) * cos(y) -+ sin(x) * sin(y)
            double cosDiff = Utils.CosPhi(wi) * Utils.CosPhi(wo) + Utils.SinPhi(wi) * Utils.SinPhi(wo);

            // Sin and tan terms
            double sinAlpha, tanBeta;

            if (Utils.AbsCosTheta(wi) > Utils.AbsCosTheta(wo))               // oTheta > iTheta
            {
                sinAlpha = Utils.SinTheta(wo);
                tanBeta  = Utils.SinTheta(wi) / Utils.AbsCosTheta(wi);
            }
            else                 // iTheta >= oTheta
            {
                sinAlpha = Utils.SinTheta(wi);
                tanBeta  = Utils.SinTheta(wo) / Utils.AbsCosTheta(wo);
            }

            return(kd * Utils.PiInv * (A + B * Math.Max(0, cosDiff) * sinAlpha * tanBeta));
        }
        /// <summary>
        /// Sample returns a single possible direction
        /// </summary>
        /// <param name="woL"></param>
        /// <returns></returns>
        public override (Spectrum, Vector3, double) Sample_f(Vector3 wo)
        {
            var F = fresnel.Evaluate(Utils.CosTheta(wo));

            bool entering = Utils.CosTheta(wo) > 0;
            var  etaI     = entering ? fresnel.EtaI : fresnel.EtaT;
            var  etaT     = entering ? fresnel.EtaT : fresnel.EtaI;

            var n = new Vector3(0, 0, 1);

            n = Vector3.Dot(n, wo) < 0 ? -n : n;

            var(refracted, wt) = Refract(wo, n, etaI / etaT);

            if (!refracted)
            {
                return(Spectrum.ZeroSpectrum, null, 0);
            }

            Spectrum ft = r * (1 - F.Max());

            var pdf = 1 - F.Max();

            return(ft / Utils.AbsCosTheta(wt), wt, pdf);
        }
Exemple #4
0
        /// <summary>
        /// Sample returns a single possible direction
        /// </summary>
        /// <param name="woL"></param>
        /// <returns></returns>
        public override (Spectrum, Vector3, double) Sample_f(Vector3 woL)
        {
            // perfect specular reflection
            Vector3  wiL = new Vector3(-woL.x, -woL.y, woL.z);
            Spectrum ft  = r * fresnel.Evaluate(Utils.CosTheta(wiL));

            return(ft / Utils.AbsCosTheta(wiL), wiL, 1);
        }
Exemple #5
0
        public override Spectrum f(Vector3 wo, Vector3 wi)
        {
            // var phiWi = Phi(wi.x, wi.y);
            // var phiWo = Phi(wo.x, wo.y);
            // var thetaWi = Theta(wi.x, wi.y, wi.z);
            // var thetaWo = Theta(wo.x, wo.y, wo.z);
            //
            // var alpha = Math.Max(thetaWi, thetaWo);
            // var beta = Math.Min(thetaWi, thetaWo);
            //
            // return kd * Utils.PiInv * (a + b * Math.Max(0, Math.Cos(phiWi - phiWo))) * Math.Sin(alpha) * Math.Tan(beta);

            var sinThetaI = Utils.SinTheta(wi);
            var sinThetaO = Utils.SinTheta(wo);
            var maxCos    = 0.0;

            if (sinThetaI > 1e-4 && sinThetaO > 1e-4)
            {
                var sinPhiI = Utils.SinPhi(wi);
                var cosPhiI = Utils.CosPhi(wi);
                var sinPhiO = Utils.SinPhi(wo);
                var cosPhiO = Utils.CosPhi(wo);
                var dCos    = cosPhiI * cosPhiO + sinPhiI * sinPhiO;
                maxCos = Math.Max(0, dCos);
            }

            double sinAlpha;
            double tanBeta;

            if (Utils.AbsCosTheta(wi) > Utils.AbsCosTheta(wo))
            {
                sinAlpha = sinThetaO;
                tanBeta  = sinThetaI / Utils.AbsCosTheta(wi);
            }
            else
            {
                sinAlpha = sinThetaI;
                tanBeta  = sinThetaO / Utils.AbsCosTheta(wo);
            }

            return(kd * Utils.PiInv * (a + b * maxCos * sinAlpha * tanBeta));
        }
Exemple #6
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;
        }
Exemple #7
0
        public Spectrum Li(Ray r, Scene s)
        {
            Spectrum L = Spectrum.ZeroSpectrum;
            Spectrum B = Spectrum.Create(1);

            int nbounces = 0;

            while (nbounces < 20)
            {
                SurfaceInteraction isect = null;

                //Get the object the ray intersected with
                isect = s.Intersect(r).Item2;

                //If the ray hasn't hit anything return 0
                if (isect == null)
                {
                    break;
                }

                Vector3 wo = isect.Wo;//-r.d;
                //If the ray hit a light, take its emission
                if (isect.Obj is Light)
                {
                    if (nbounces == 0)
                    {
                        L = B * isect.Le(wo);
                    }
                    break;
                }

                //Create a light ray from the intersection point and add its emission
                Spectrum Ld = Light.UniformSampleOneLight(isect, s);
                L = L.AddTo(B * Ld);


                //Get the materials value at this point
                (Spectrum f, Vector3 wi, double pr, bool specular) = (isect.Obj as Shape).BSDF.Sample_f(wo, isect);

                if (!specular)
                {
                    B = B * f * Utils.AbsCosTheta(wi) / pr;
                }


                //Spawn a new ray from the intersection
                r = isect.SpawnRay(wi);

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

            return(L);
        }
 public override double Pdf(Vector3 wo, Vector3 wi)
 {
     //return Utils.CosTheta(wi) * Utils.PiInv;
     //return !Utils.SameHemisphere(wo, wi) ? Utils.AbsCosTheta(wi) * Utils.PiInv : 0;
     return(Utils.AbsCosTheta(wi) * Utils.PiInv);
 }