public static bool Contains3DPoint(Vector3 point, bool checkOnPlane, Vector3 quadCenter, float quadWidth, float quadHeight, Vector3 quadRight, Vector3 quadUp, QuadEpsilon epsilon = new QuadEpsilon()) { Plane quadPlane = new Plane(Vector3.Cross(quadRight, quadUp).normalized, quadCenter); if (checkOnPlane && quadPlane.GetAbsDistanceToPoint(point) > epsilon.ExtrudeEps) { return(false); } quadWidth += epsilon.WidthEps; quadHeight += epsilon.HeightEps; Vector3 toPoint = point - quadCenter; float dotRight = toPoint.AbsDot(quadRight); float dotUp = toPoint.AbsDot(quadUp); if (dotRight > quadWidth * 0.5f) { return(false); } if (dotUp > quadHeight * 0.5f) { return(false); } return(true); }
public override Vector3 Sample_F(ShadeRec sr, Vector3 wo, ref Vector3 wr) { float ndotwo = Vector3.Dot(sr.Normal, wo); wr = -wo + 2.0f * sr.Normal * ndotwo; return(fresnel(sr) * Colors.White / Vector3.AbsDot(sr.Normal, wr)); }
public override Vector3 Sample_F(ShadeRec sr, Vector3 wo, ref Vector3 wi) { float ndotwo = Vector3.Dot(sr.Normal, wo); wi = -wo + 2.0f * sr.Normal * ndotwo; return(kr * cr.GetColor(sr) / Vector3.AbsDot(sr.Normal, wi)); }
// public float Pdf(Vector3 <float> wo, Vector3 <float> wh) { if (sampleVisibleArea) { return(D(wh) * G1(wo) * Vector3 <float> .AbsDot(wo, wh) / BxDF.AbsCosTheta(wo)); } else { return(D(wh) * BxDF.AbsCosTheta(wo)); } }
public virtual float Pdf(Interaction inter, Vector3 <float> wi) { var ray = inter.SpawnRay(wi); if (!Intersect(ray, out float tHit, out SurfaceInteraction intersection)) { return(0); } return((inter.P - intersection.P).LengthSquared() / (Vector3 <float> .AbsDot(-wi, intersection.N) * Area())); }
public static bool IsAligned(this Vector3 vector, Vector3 other, bool checkSameDirection) { if (!checkSameDirection) { float absDot = vector.AbsDot(other); return(Mathf.Abs(absDot - 1.0f) < 1e-5f); } else { float dot = vector.Dot(other); return(dot > 0.0f && Mathf.Abs(dot - 1.0f) < 1e-5f); } }
public static int GetMostAligned(Vector3[] vectors, Vector3 dir, bool checkSameDirection) { if (vectors.Length == 0) { return(-1); } float bestAlignment = float.MinValue; int bestIndex = -1; if (!checkSameDirection) { // Loop through each test vector for (int dirIndex = 0; dirIndex < vectors.Length; ++dirIndex) { // Calculate the absolute dot product with 'dir'. If this is gerater // than what we have so far, it means we found vector which is more // aligned with 'dir'. Vector3 testDir = vectors[dirIndex]; float absDot = testDir.AbsDot(dir); if (absDot > bestAlignment) { bestAlignment = absDot; bestIndex = dirIndex; } } return(bestIndex); } else { // Loop through each test vector for (int dirIndex = 0; dirIndex < vectors.Length; ++dirIndex) { // Calculate the dot product with 'dir'. If this is gerater than 0 // and greater than what we have so far, it means we found vector // which is more aligned with 'dir'. Vector3 testDir = vectors[dirIndex]; float dot = testDir.Dot(dir); if (dot > 0.0f && dot > bestAlignment) { bestAlignment = dot; bestIndex = dirIndex; } } return(bestIndex); } }
public override Vector3 Sample_F(ShadeRec sr, Vector3 wo, ref Vector3 wt) { Vector3 n = (sr.Normal); float cos_thetai = Vector3.Dot(n, wo); float eta = eta_in / eta_out; if (cos_thetai < 0.0) { cos_thetai = -cos_thetai; n = -n; eta = 1.0f / eta; } float temp = 1.0f - (1.0f - cos_thetai * cos_thetai) / (eta * eta); float cos_theta2 = MathUtil.Sqrt(temp); wt = -wo / eta - (cos_theta2 - cos_thetai / eta) * n; return(fresnel(sr) / (eta * eta) * Colors.White / Vector3.AbsDot(sr.Normal, wt)); }
private Spectrum SpecularReflect(RayDifferential ray, SurfaceInteraction inter, Scene scene, Camera camera, Sampler sampler, int depth) { // Sample a direction with the BSDF var type = BxDFType.Reflection | BxDFType.Specular; var f = inter.Bsdf.Sample_f(inter.Wo, out Vector3 <float> wi, sampler.Get2D(), out float pdf, type, out BxDF.BxDFType sampledType); // Add the contribution of this reflection if (pdf > 0 && !f.IsBlack() && Vector3 <float> .AbsDot(wi, inter.Shading.N) != 0) { var newRay = inter.SpawnRay(wi).ToDiff(); if (ray.HasDifferentials) { // TODO } return(f * Li(newRay, scene, camera, sampler, depth + 1) * Vector3 <float> .AbsDot(wi, inter.Shading.N) * (1.0f / pdf)); } return(Spectrum.Zero); }
public override Vector3 Shade(ShadeRec sr) { Vector3 L = base.Shade(sr); Vector3 wo = -sr.Ray.Direction; Vector3 wi = Vector3.Zero(); Vector3 fr = reflective.Sample_F(sr, wo, ref wi); Ray reflected_ray = new Ray(sr.HitPoint, wi); if (specular_btdf.TIR(sr)) { L += sr.World.Tracer.TraceRay(reflected_ray, sr.Depth + 1); } else { Vector3 wt = Vector3.Zero(); Vector3 ft = specular_btdf.Sample_F(sr, wo, ref wt); Ray transmitted_ray = new Ray(sr.HitPoint, wt); L += fr * sr.World.Tracer.TraceRay(reflected_ray, sr.Depth + 1) * Vector3.AbsDot(sr.Normal, wi); L += ft * sr.World.Tracer.TraceRay(transmitted_ray, sr.Depth + 1) * Vector3.AbsDot(sr.Normal, wt); //this is very important for transparent rendering } return(L); }
public static Spectrum EstimateDirect(Interaction inter, Point2 <float> scattering, Light light, Point2 <float> lightPoint, Scene scene, Sampler sampler, bool specular = false) { var bsdfType = specular ? BxDFType.All : BxDFType.All & ~BxDFType.Specular; var Ld = Spectrum.Zero; float scatteringPdf, lightPdf; // Sampling the BSDF works well with highly specular materials and large light sources. // Sampling the light source works well with small sources and rough materials. // // To handle most cases, we do both: // 1. Sample the light source (gives a radiance, a PDF, an incoming direction) // -> evaluate the BSDF for those parameters // 2. Sample the BSDF // -> compute the radiance along the incoming direction // 1. Sample the light source var Li = light.Sample_Li(inter, lightPoint, out Vector3 <float> wi, out lightPdf, out VisibilityTester visibility); if (lightPdf > 0 && !Li.IsBlack()) { // Evaluate the BSDF value for the light sample Spectrum f; if (inter.IsSurfaceInteraction()) { var sinter = (SurfaceInteraction)inter; f = sinter.Bsdf.f(sinter.Wo, wi, bsdfType) * Vector3 <float> .AbsDot(wi, sinter.Shading.N); scatteringPdf = sinter.Bsdf.Pdf(sinter.Wo, wi, bsdfType); } else { // Medium interaction throw new NotImplementedException(); } if (!f.IsBlack() && visibility.Unoccluded(scene)) { // Delta lights: do not apply multiple importance sampling if (light.IsDeltaLight()) { Ld += f * Li / lightPdf; } else { var weight = MathUtils.PowerHeuristic(1, lightPdf, 1, scatteringPdf); Ld += f * Li * weight / lightPdf; } } } // 2. Sample the BSDF if (!light.IsDeltaLight()) { var sampledSpecular = false; // Sample scattered direction Spectrum f; if (inter.IsSurfaceInteraction()) { var sinter = (SurfaceInteraction)inter; f = sinter.Bsdf.Sample_f(sinter.Wo, out wi, scattering, out scatteringPdf, bsdfType, out BxDFType sampledType); f *= Vector3 <float> .AbsDot(wi, sinter.Shading.N); sampledSpecular = (sampledType & BxDFType.Specular) > 0; } else { // Medium interaction throw new NotImplementedException(); } if (!f.IsBlack() && scatteringPdf > 0) { var weight = 1f; if (!sampledSpecular) { lightPdf = light.Pdf_Li(inter, wi); if (lightPdf == 0) { return(Ld); } weight = MathUtils.PowerHeuristic(1, scatteringPdf, 1, lightPdf); } // Transmittance would be done here var Tr = Spectrum.One; var ray = inter.SpawnRay(wi); var foundSurfaceInteraction = scene.Intersect(ray, out SurfaceInteraction lightInter); // Add light contribution Li = Spectrum.Zero; if (foundSurfaceInteraction) { if (lightInter.Primitive.GetAreaLight() == light) { Li = lightInter.Le(-wi); } } else { //Li = light.Le(ray); } if (!Li.IsBlack()) { Ld += f * Li * Tr * weight / scatteringPdf; } } } return(Ld); }
public override Spectrum Li(RayDifferential ray, Scene scene, Camera camera, Sampler sampler, int depth = 0) { var L = Spectrum.Zero; // If the ray doesn't intersect the scene, return the background radiance if (!scene.Intersect(ray, out SurfaceInteraction inter) || inter == null) { foreach (var light in scene.Lights) { L += light.Le(ray); } return(L); } // If the ray intersects something, we need to compute how the light is scattered var n = inter.Shading.N; var wo = inter.Wo; inter.ComputeScatteringFunctions(ray); // Add the emissive contribution of the intersected object L += inter.Le(wo); // Add the direct contribution of each light source foreach (var light in scene.Lights) { // Sample the light source var Li = light.Sample_Li(inter, sampler.Get2D(), out Vector3 <float> wi, out float pdf, out VisibilityTester visibility); if (Li.IsBlack() || pdf == 0) { continue; } // Evaluate the scattering at the interaction point var f = inter.Bsdf.f(wo, wi); // Trace a shadow ray to check that the point receives light if (!f.IsBlack()) { if (visibility.Unoccluded(scene)) { L += f * Li * Vector3 <float> .AbsDot(wi, n.ToVector3()) * (1.0f / pdf); } /*else * L = new Spectrum(0, 0, 50);*/ } else { } } // Recursively trace new rays if (depth + 1 < maxDepth) { L += SpecularReflect(ray, inter, scene, camera, sampler, depth); //L += SpecularTransmit(ray, inter, scene, sampler, depth); } return(L); }