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); }
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); }
/// <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); }
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)); }
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; }
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); }