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); }
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); }
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)); }
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)); }
public override double Pdf(SurfaceInteraction si, Vector3 wi) { //throw new NotImplementedException(); // Zakaj nikoli ne pride sm ? return(Utils.PiInv / 4.0); }
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)); }
public override Spectrum L(SurfaceInteraction intr, Vector3 w) { if (onesided) { return((Vector3.Dot(intr.Normal, w) > 0) ? Lemit : Spectrum.ZeroSpectrum); } else { return(Lemit); } }
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))); }
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); }
/// <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); }
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); }
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)); }
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); }
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); }
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); }
/// <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); }
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(); }
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)); }
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); }
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); }
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); }
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)); }
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)); }
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)); }
public abstract Spectrum L(SurfaceInteraction si, Vector3 w);
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)); }
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))); }
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_Li(SurfaceInteraction si, Vector3 wi) { return(shape.Pdf(si, wi)); }
public override double Pdf(SurfaceInteraction si, Vector3 wi) { throw new NotImplementedException(); }