예제 #1
0
파일: Sphere.cs 프로젝트: ZBabnik/nrg_hw2
        public override (SurfaceInteraction, double) Sample()
        {
            // TODO: Implement Sphere sampling
            if (Outside)
            {
                var pObj = this.Radius * Samplers.UniformSampleSphere();
                var n    = new Vector3(pObj.x, pObj.y, pObj.z);
                var pdf  = 1 / this.Area();
                var dpdu = new Vector3(-pObj.y, pObj.x, 0);

                SurfaceInteraction si = new SurfaceInteraction(pObj, n, Vector3.ZeroVector, dpdu, this);
                return(ObjectToWorld.Apply(si), pdf);
            }
            else
            {
                var pObj = this.Radius * Samplers.UniformSampleSphere();
                var n    = new Vector3(pObj.x, pObj.y, pObj.z);
                var pdf  = 1 / this.Area();
                var dpdu = new Vector3(-pObj.y, pObj.x, 0);

                SurfaceInteraction si = new SurfaceInteraction(pObj, -n, Vector3.ZeroVector, dpdu, this);
                return(ObjectToWorld.Apply(si), pdf);
            }

            // TODO: Return surface interaction and pdf

            // A dummy return example
            //double dummyPdf = 1.0;
            //Vector3 dummyVector = new Vector3(0, 0, 0);
            //SurfaceInteraction dummySurfaceInteraction = new SurfaceInteraction(dummyVector, dummyVector, dummyVector, dummyVector, this);
            //return (dummySurfaceInteraction, dummyPdf);
        }
예제 #2
0
        public (Spectrum, Vector3, double, bool) Sample_f(Vector3 woW, SurfaceInteraction si)
        {
            var woL = WorldToLocal(woW, si);

            if (Math.Abs(woL.z) < Renderer.Epsilon)
            {
                return(Spectrum.ZeroSpectrum, Vector3.ZeroVector, 0, false);
            }

            // randomly choose bxdf
            int comp = (int)Math.Floor(ThreadSafeRandom.NextDouble() * bxdfs.Count);
            var bxdf = bxdfs[comp];

            // Sample chosen _BxDF_
            (Spectrum f, Vector3 wiL, double pdf) = bxdf.Sample_f(woL);

            if (pdf < Renderer.Epsilon)
            {
                Console.WriteLine("Zero pfd");
                return(Spectrum.ZeroSpectrum, Vector3.ZeroVector, 0, false);
            }

            // Compute overall PDF & f with all BxDFs
            foreach (var bx in bxdfs.Where(x => x != bxdf))
            {
                pdf += bx.Pdf(woL, wiL);
                f.AddTo(bx.f(woL, wiL));
            }
            pdf /= bxdfs.Count;

            var wiW = LocalToWorld(wiL, si);

            return(f, wiW, pdf, bxdf.IsSpecular);
        }
예제 #3
0
        public override (double?, SurfaceInteraction) Intersect(Ray _r)
        {
            Ray ray = WorldToObject.Apply(_r);

            double a = 1;
            double b = 2 * Vector3.Dot(ray.o, ray.d);
            double c = Vector3.Dot(ray.o, ray.o) - Radius * Radius;

            (bool hasSolution, double t0, double t1) = Utils.Quadratic(a, b, c);

            if (!hasSolution || (t0 < Renderer.Epsilon && t1 < Renderer.Epsilon))
            {
                return(null, null);
            }

            double tHit = (t0 < Renderer.Epsilon ? t1 : t0);

            Vector3 pHit   = ray.Point(tHit);
            Vector3 normal = pHit * (1.0 / Radius);
            Vector3 dpdu   = new Vector3(-pHit.y, pHit.x, 0);

            SurfaceInteraction si = new SurfaceInteraction(pHit, normal, -ray.d, dpdu, this);

            return(tHit, ObjectToWorld.Apply(si));
        }
예제 #4
0
        public override (double?, SurfaceInteraction) Intersect(Ray r)
        {
            var ray = WorldToObject.Apply(r);

            // Compute plane intersection for quad

            // Reject intersections for rays parallel to the quad's plane
            if (ray.d.z == 0)
            {
                return(null, null);
            }

            double tShapeHit = -ray.o.z / ray.d.z;

            if (tShapeHit <= Renderer.Epsilon)
            {
                return(null, null);
            }

            // See if hit point is inside
            var pHit = ray.Point(tShapeHit);

            if (pHit.x < -width / 2 || pHit.x > width / 2 || pHit.y < -height / 2 || pHit.y > height / 2)
            {
                return(null, null);
            }

            // Refine disk intersection point
            pHit.z = 0;
            var dpdu = new Vector3(1, 0, 0);

            var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this);

            return(tShapeHit, ObjectToWorld.Apply(si));
        }
예제 #5
0
        public override double Pdf(SurfaceInteraction si, Vector3 wi)
        {
            //throw new NotImplementedException();

            // Zakaj nikoli ne pride sm ?
            return(Utils.PiInv / 4.0);
        }
예제 #6
0
파일: Transform.cs 프로젝트: rokpv/nrg-dn2
        public SurfaceInteraction Apply(SurfaceInteraction si)
        {
            var p    = ApplyPoint(si.Point);
            var n    = ApplyNormal(si.Normal);
            var w    = ApplyVector(si.Wo);
            var dpdu = ApplyVector(si.Dpdu);

            return(new SurfaceInteraction(p, n, w, dpdu, si.Obj));
        }
예제 #7
0
 public override Spectrum L(SurfaceInteraction intr, Vector3 w)
 {
     if (onesided)
     {
         return((Vector3.Dot(intr.Normal, w) > 0) ? Lemit : Spectrum.ZeroSpectrum);
     }
     else
     {
         return(Lemit);
     }
 }
예제 #8
0
        public double Pdf(Vector3 woW, Vector3 wiW, SurfaceInteraction si)
        {
            Vector3 wo = WorldToLocal(woW, si);
            Vector3 wi = WorldToLocal(wiW, si);

            if (wo.z == 0)
            {
                return(0);
            }
            return(bxdfs.Average(x => x.Pdf(wo, wi)));
        }
예제 #9
0
        public override (SurfaceInteraction, double) Sample()
        {
            Vector3 sample = Samplers.UniformSampleSphere();
            Vector3 point  = sample * Radius;
            Vector3 normal = sample;
            Vector3 dpdu   = new Vector3(-normal.y, normal.x, 0.0);
            double  pdf    = 1.0 / Area();

            SurfaceInteraction si = new SurfaceInteraction(point, normal, Vector3.ZeroVector, dpdu, this);

            return(ObjectToWorld.Apply(si), pdf);
        }
예제 #10
0
        /// <summary>
        /// Samples light ray at source point
        /// </summary>
        /// <param name="source"></param>
        /// <returns>Spectrum, wi, pdf, point on light</returns>
        public override (Spectrum, Vector3, double, Vector3) Sample_Li(SurfaceInteraction source)
        {
            (SurfaceInteraction pShape, double pdf) = shape.Sample(source);

            if (pdf == 0 || (pShape.Point - source.Point).LengthSquared() < Renderer.Epsilon)
            {
                return(Spectrum.ZeroSpectrum, Vector3.ZeroVector, 0, Vector3.ZeroVector);
            }

            var wi = (pShape.Point - source.Point).Normalize();
            var Li = L(pShape, -wi);

            return(Li, wi, pdf, pShape.Point);
        }
예제 #11
0
파일: Light.cs 프로젝트: rokcej/path-tracer
        private Spectrum EstimateLWithIS(SurfaceInteraction it, Scene s)
        {
            // Sample light source with importance sampling
            (Spectrum Li, Vector3 wi, double lightPdf, Vector3 lightPt) = Sample_Li(it);

            if (!s.Unoccluded(it.Point, lightPt) || lightPdf == 0)
            {
                return(Spectrum.ZeroSpectrum);
            }

            var      shp = it.Obj as Shape;
            Spectrum f   = shp.BSDF.f(it.Wo, wi, it) * Vector3.AbsDot(wi, it.Normal);

            return(f * Li / lightPdf);
        }
예제 #12
0
        public override double Pdf(SurfaceInteraction _si, Vector3 wi)
        {
            SurfaceInteraction si    = WorldToObject.Apply(_si);
            double             dist2 = si.Point.LengthSquared();

            if (dist2 <= Radius * Radius)
            {
                // Point inside sphere
                return(base.Pdf(_si, wi));
            }
            // Point outside sphere
            double sinThetaMax = Radius / Math.Sqrt(dist2);
            double cosThetaMax = Utils.SinToCos(sinThetaMax);

            return(Samplers.UniformConePdf(cosThetaMax));
        }
예제 #13
0
        public override (SurfaceInteraction, double) Sample(SurfaceInteraction _si)
        {
            SurfaceInteraction si  = WorldToObject.Apply(_si);
            double             dc2 = si.Point.LengthSquared();

            if (dc2 <= Radius * Radius)
            {
                // Point inside sphere
                return(base.Sample(_si));
            }

            // Point outside sphere
            double dc = Math.Sqrt(dc2);

            double sinThetaMax = Radius / dc;
            double cosThetaMax = Utils.SinToCos(sinThetaMax);

            // Determine theta and phi for uniform cone sampling
            double cosTheta = (cosThetaMax - 1) * Samplers.ThreadSafeRandom.NextDouble() + 1;
            double sinTheta = Utils.CosToSin(cosTheta);
            double phi      = Samplers.ThreadSafeRandom.NextDouble() * 2.0 * Math.PI;

            // Distance between reference point and sample point on sphere
            double ds = dc * cosTheta - Math.Sqrt(Math.Max(0, Radius * Radius - dc2 * sinTheta * sinTheta));

            // Kosinusni zakon
            double cosAlpha = (dc2 + Radius * Radius - ds * ds) / (2 * dc * Radius);
            double sinAlpha = Utils.CosToSin(cosAlpha);

            // Construct coordinate system and use phi and theta as spherical coordinates to get point on sphere
            Vector3 wcZ = si.Point.Clone().Normalize();

            (Vector3 wcX, Vector3 wcY) = Utils.CoordinateSystem(wcZ);

            Vector3 nObj = Utils.SphericalDirection(sinAlpha, cosAlpha, phi, wcX, wcY, wcZ);
            Vector3 pObj = nObj * Radius;

            // Surface interaction
            Vector3            dpdu     = new Vector3(-nObj.y, nObj.x, 0.0);
            SurfaceInteraction siSample = new SurfaceInteraction(pObj, nObj, Vector3.ZeroVector, dpdu, this);

            // Uniform cone PDF
            double pdf = Samplers.UniformConePdf(cosThetaMax);

            return(ObjectToWorld.Apply(siSample), pdf);
        }
예제 #14
0
        public Spectrum f(Vector3 woW, Vector3 wiW, SurfaceInteraction si)
        {
            var wi = WorldToLocal(wiW, si);
            var wo = WorldToLocal(woW, si);
            var f  = Spectrum.ZeroSpectrum;

            if (Math.Abs(wo.z) < Renderer.Epsilon)
            {
                return(f);
            }

            foreach (var bx in bxdfs)
            {
                f.AddTo(bx.f(wo, wi));
            }
            return(f);
        }
예제 #15
0
파일: Light.cs 프로젝트: rokcej/path-tracer
        public static Spectrum UniformSampleOneLight(SurfaceInteraction it, Scene s)
        {
            // Randomly choose a single light to sample, _light_
            int nLights = s.Lights.Count;

            if (nLights == 0)
            {
                return(Spectrum.ZeroSpectrum);
            }

            int    lightNum = (int)Math.Floor(ThreadSafeRandom.NextDouble() * nLights);
            double lightPdf = 1 / (double)nLights;

            var light = s.Lights[lightNum];

            return(light.EstimateLWithIS(it, s) / lightPdf);
        }
예제 #16
0
파일: Scene.cs 프로젝트: rokpv/nrg-dn2
        /// <summary>
        /// Finds closest intersection of ray with scene
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public (double?, SurfaceInteraction) Intersect(Ray r)
        {
            double?            mint = null;
            SurfaceInteraction si   = null;

            foreach (var sh in Elements)
            {
                (double?t, SurfaceInteraction shi) = sh.Intersect(r);
                if (t.HasValue && t > Renderer.Epsilon && (!mint.HasValue || t < mint))
                {
                    mint = t.Value;
                    si   = shi;
                }
            }

            return(mint, si);
        }
예제 #17
0
파일: Sphere.cs 프로젝트: ZBabnik/nrg_hw2
        public override double Pdf(SurfaceInteraction si, Vector3 wi)
        {
            var pCenter = this.WorldToObject.ApplyVector(Vector3.ZeroVector);
            var pOrigin = si.Point;

            if ((pOrigin - pCenter).LengthSquared() <= this.Radius * this.Radius)
            {
                return((this as Shape).Pdf(si, wi));
            }

            double sinThetaMax2 = Radius * Radius / (si.Point - pCenter).LengthSquared();
            double cosThetaMax  = Math.Sqrt(Math.Max((double)0, 1 - sinThetaMax2));

            return(1 / (2 * Math.PI * (1 - cosThetaMax)));

            //throw new NotImplementedException();
        }
예제 #18
0
        public override (SurfaceInteraction, double) Sample()
        {
            // TODO: Implement Sphere sampling
            var center = new Vector3(0, 0, 0);
            var point  = center + Radius * Samplers.UniformSampleSphere();

            var normal = point.Normalize();

            if (innerOrientation)
            {
                normal = -normal;
            }

            point *= Radius / (center - point).Length();
            var wo          = point;
            var dpdu        = Dpdu(point);
            var interaction = new SurfaceInteraction(point, normal, wo, dpdu, this);

            return(ObjectToWorld.Apply(interaction), Pdf(interaction, point));
        }
예제 #19
0
        public override Spectrum L(SurfaceInteraction intr, Vector3 w)
        {
            double dot = 0;

            switch (side)
            {
            case SideEnum.Front:
                dot = Vector3.Dot(intr.Normal, w);
                break;

            case SideEnum.Back:
                dot = Vector3.Dot(-intr.Normal, w); // Flip normal
                break;

            case SideEnum.Both:
                dot = Vector3.AbsDot(intr.Normal, w); // Get absolute dot product
                break;
            }
            return((dot > 0) ? Lemit : Spectrum.ZeroSpectrum);
        }
예제 #20
0
        public virtual (SurfaceInteraction, double) Sample(SurfaceInteraction si)
        {
            (SurfaceInteraction intr, double pdf) = Sample();
            var wi = intr.Point - si.Point;

            if (wi.LengthSquared() < Renderer.Epsilon)
            {
                pdf = 0;
            }
            else
            {
                wi.Normalize();
                // Convert from area measure, as returned by the Sample() call above, to solid angle measure.
                pdf *= (si.Point - intr.Point).LengthSquared() / Vector3.AbsDot(intr.Normal, -wi);
                if (double.IsInfinity(pdf))
                {
                    pdf = 0;
                }
            }
            return(intr, pdf);
        }
예제 #21
0
        public virtual double Pdf(SurfaceInteraction si, Vector3 wi)
        {
            // Intersect sample ray with area light geometry
            Ray ray = si.SpawnRay(wi);

            (double?tHit, SurfaceInteraction isectLight) = Intersect(ray);

            if (!tHit.HasValue)
            {
                return(0);
            }

            // Convert area measure to solid angle measure
            double pdf = (si.Point - isectLight.Point).LengthSquared() / (Vector3.AbsDot(isectLight.Normal, -wi) * Area());

            if (double.IsInfinity(pdf))
            {
                pdf = 0;
            }
            return(pdf);
        }
예제 #22
0
        public override (double?, SurfaceInteraction) Intersect(Ray r)
        {
            Ray ray = WorldToObject.Apply(r);

            var ox = ray.o.x;
            var oy = ray.o.y;
            var oz = ray.o.z;

            var dx = ray.d.x;
            var dy = ray.d.y;
            var dz = ray.d.z;

            var a = dx * dx + dy * dy + dz * dz;
            var b = 2 * (dx * ox + dy * oy + dz * oz);
            var c = ox * ox + oy * oy + oz * oz - Radius * Radius;

            var(solvable, t0, t1) = Utils.Quadratic(a, b, c);
            if (!solvable)
            {
                return(null, null);
            }

            var shapeHit = t0 <= 0 ? t1 : t0;

            var hit = ray.Point(shapeHit);

            hit *= Radius / hit.Length();

            if (Math.Abs(hit.x) < Double.Epsilon && Math.Abs(hit.y) < double.Epsilon)
            {
                hit.x = 1e-5 * Radius;
            }

            var dpdu   = Dpdu(hit);
            var normal = innerOrientation ? -hit : hit;

            var interaction = new SurfaceInteraction(hit, normal, -ray.d, dpdu, this);

            return(shapeHit, ObjectToWorld.Apply(interaction));
        }
예제 #23
0
        public override (double?, SurfaceInteraction) Intersect(Ray ray)
        {
            Ray r = WorldToObject.Apply(ray);

            // Compute quadratic sphere coefficients

            // Initialize _double_ ray coordinate values
            double a = r.d.x * r.d.x + r.d.y * r.d.y + r.d.z * r.d.z;
            double b = 2 * (r.d.x * r.o.x + r.d.y * r.o.y + r.d.z * r.o.z);
            double c = r.o.x * r.o.x + r.o.y * r.o.y + r.o.z * r.o.z - Radius * Radius;

            // Solve quadratic equation for _t_ values
            (bool s, double t0, double t1) = Utils.Quadratic(a, b, c);

            if (!s)
            {
                return(null, null);
            }

            // Check quadric shape _t0_ and _t1_ for nearest intersection
            if (t1 <= 0)
            {
                return(null, null);
            }

            double tShapeHit = t0;

            if (tShapeHit <= Renderer.Epsilon)
            {
                tShapeHit = t1;
            }

            // Compute sphere hit position and $\phi$
            var pHit = r.Point(tShapeHit);
            var dpdu = new Vector3(-pHit.y, pHit.x, 0);
            var si   = new SurfaceInteraction(pHit, pHit.Clone().Normalize(), -r.d, dpdu, this);

            return(tShapeHit, ObjectToWorld.Apply(si));
        }
예제 #24
0
        public override (double?, SurfaceInteraction) Intersect(Ray r)
        {
            var ray = WorldToObject.Apply(r);

            // Compute plane intersection for disk

            // Reject disk intersections for rays parallel to the disk's plane
            if (ray.d.z == 0)
            {
                return(null, null);
            }

            double tShapeHit = (height - ray.o.z) / ray.d.z;

            if (tShapeHit <= Renderer.Epsilon)
            {
                return(null, null);
            }

            // See if hit point is inside disk radii and $\phimax$
            var pHit  = ray.Point(tShapeHit);
            var dist2 = pHit.x * pHit.x + pHit.y * pHit.y;

            if (dist2 > radius * radius + Renderer.Epsilon)
            {
                return(null, null);
            }

            // Refine disk intersection point
            pHit.z = height;

            var dpdu = new Vector3(-pHit.y, pHit.x, 0);

            var si = new SurfaceInteraction(pHit, new Vector3(0, 0, 1), -ray.d, dpdu, this);

            return(tShapeHit, ObjectToWorld.Apply(si));
        }
예제 #25
0
파일: Light.cs 프로젝트: rokcej/path-tracer
 public abstract Spectrum L(SurfaceInteraction si, Vector3 w);
예제 #26
0
 private Vector3 LocalToWorld(Vector3 v, SurfaceInteraction si)
 {
     return(new Vector3(si.Dpdu.x * v.x + si.Dpdv.x * v.y + si.Normal.x * v.z,
                        si.Dpdu.y * v.x + si.Dpdv.y * v.y + si.Normal.y * v.z,
                        si.Dpdu.z * v.x + si.Dpdv.z * v.y + si.Normal.z * v.z));
 }
예제 #27
0
 private Vector3 WorldToLocal(Vector3 v, SurfaceInteraction si)
 {
     return(new Vector3(Vector3.Dot(v, si.Dpdu), Vector3.Dot(v, si.Dpdv), Vector3.Dot(v, si.Normal)));
 }
예제 #28
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);
        }
예제 #29
0
 public override double Pdf_Li(SurfaceInteraction si, Vector3 wi)
 {
     return(shape.Pdf(si, wi));
 }
예제 #30
0
 public override double Pdf(SurfaceInteraction si, Vector3 wi)
 {
     throw new NotImplementedException();
 }