public DiffuseAreaLight(Shape s, Spectrum l, double intensity = 1, SideEnum sd = SideEnum.Front) { shape = s; Lemit = l * intensity; side = sd; }
public Spectrum AddTo(Spectrum v2) { c += v2.c; return(this); }
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 Lambertian(Spectrum r) { kd = r; }
public OrenNayar(Spectrum r, double roughness) { kd = r; this.cov = roughness * roughness; }
public Spectrum Li(Ray ray, Scene s) { var L = Spectrum.ZeroSpectrum; var beta = Spectrum.Create(1.0); bool specularBounce = false; for (int nBounces = 0; nBounces < 20; nBounces++) { (double?d, SurfaceInteraction si) = s.Intersect(ray); Vector3 wo = -ray.d; if (nBounces == 0 || specularBounce) { if (d != null) { L.AddTo(beta * si.Le(wo)); } else { foreach (var light in s.Lights) { L.AddTo(beta * Spectrum.ZeroSpectrum); // light.Le() } } } if (d == null) { break; } if (si.Obj is Light) { //if (nBounces == 0) //{ // L.AddTo(beta * si.Le(wo)); //} break; } if (!specularBounce) { L.AddTo(beta * Light.UniformSampleOneLight(si, s)); } (Spectrum f, Vector3 wiW, double pdf, bool bxdfIsSpecular) = ((Shape)si.Obj).BSDF.Sample_f(wo, si); specularBounce = bxdfIsSpecular; if (f.IsBlack() || pdf == 0) { break; } var wi = si.SpawnRay(wiW); beta = beta * f * Vector3.AbsDot(wiW, si.Normal) / pdf; ray = wi; if (nBounces > 3) { double q = 1 - beta.Max(); if (ThreadSafeRandom.NextDouble() < q) { break; } beta = beta / (1 - q); } } return(L); }
public SpecularTransmission(Spectrum r, double fresnel1, double fresnel2) { this.r = r; fresnel = new FresnelDielectric(fresnel1, fresnel2); }
/// <summary> /// Generate Cornell Box Geometry /// </summary> /// <returns></returns> public static Scene CornellBox() { var s = new Scene() { CameraOrigin = new Vector3(278, 274.4, -548), AspectRatio = 1.0 / 1.0, ImagePlaneWidth = 5.2 }; Shape el; // floor el = new Quad(556.0, 559.2, Transform.Translate(556.0 / 2, 0, 559.2 / 2).A(Transform.RotateX(-90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Gray))); s.Elements.Add(el); // celing el = new Quad(556.0, 559.2, Transform.Translate(556.0 / 2, 548.8, 559.2 / 2).A(Transform.RotateX(90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Gray))); s.Elements.Add(el); // back el = new Quad(556.0, 548.8, Transform.Translate(556.0 / 2, 548.8 / 2, 559.2).A(Transform.RotateX(180))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Gray))); s.Elements.Add(el); //right el = new Quad(559.2, 548.8, Transform.Translate(556.0, 548.8 / 2, 559.2 / 2).A(Transform.RotateY(90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Gray))); s.Elements.Add(el); //left el = new Quad(559.2, 548.8, Transform.Translate(0, 548.8 / 2, 559.2 / 2).A(Transform.RotateY(-90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Gray))); s.Elements.Add(el); double shade = 1; double intensity = 20; s.Elements.Add(new DiffuseAreaLight(new Quad(556, 200, Transform.Translate(278, 548, 559.2 - 400).A(Transform.RotateX(90))), Spectrum.Create(1), intensity)); s.Elements.Add(new DiffuseAreaLight(new Quad(556, 200, Transform.Translate(278, 0.1, 559.2 - 400).A(Transform.RotateX(270))), Spectrum.Create(1), intensity)); //s.Elements.Add(new RectangleLight(new Quad(556, 200, Transform.Translate(278, 548.8 / 2, 559.2 - 200).A(Transform.RotateX(270))), Spectrum.Create(1), intensity, false)); //s.Elements.Add(new RectangleLight(new Quad(100, 200, Transform.Translate(278, 548.8 * 3 / 4, 559.2 - 200).A(Transform.RotateX(270))), Spectrum.Create(1), intensity, false)); //s.Elements.Add(new RectangleLight(new Quad(100, 200, Transform.Translate(278, 548.8 * 1 / 4, 559.2 - 200).A(Transform.RotateX(270))), Spectrum.Create(1), intensity, false)); //left //s.Elements.Add(new DiffuseAreaLight(new Quad(548.8, 556.0, Transform.Translate(0.1, 548.8 / 2, 559.2).A(Transform.RotateY(90))), Spectrum.Create(shade), intensity)); //right //s.Elements.Add(new DiffuseAreaLight(new Quad(548.8, 556.0, Transform.Translate(555.9, 548.8 / 2, 559.2).A(Transform.RotateY(270))), Spectrum.Create(shade), intensity)); //s.Elements.Add(new DiffuseAreaLight(new Disk(80, 0.1, Transform.Translate(278, 0, 280).A(Transform.RotateX(-90))), Spectrum.Create(1), 20)); //s.Elements.Add(new RectangleLight(new Quad(160, 80, Transform.Translate(278, 278, 350).A(Transform.RotateX(135))), Spectrum.Create(1), 20)); double gridSize = 4; double sphereSize = 70; double offsetX = 550 / gridSize; double offsetY = 550 / gridSize; double row = 0; double column = 0; double z = 400; string[] models = { "beige-fabric", "yellow-matte-plastic", "green-plastic", "neoprene-rubber", "blue-rubber", "polyurethane-foam", "special-walnut-224", "yellow-phenolic", "green-metallic-paint", "red-metallic-paint", "violet-acrylic", "grease-covered-steel", "aluminium", "alum-bronze", "two-layer-silver", "two-layer-gold" }; foreach (string model in models) { el = new Sphere(sphereSize, Transform.Translate((column + 0.5) * offsetX, (row + 0.5) * offsetY, z)); column++; if (column % gridSize == 0) { row++; column = 0; } el.BSDF.Add(new MERL(model, true)); //el.BSDF.Add(new SpecularReflection(Spectrum.ZeroSpectrum.FromRGB(Color.White), 1, 1.5)); s.Elements.Add(el); } return(s); }
/// <summary> /// Generate Cornell Box Geometry /// </summary> /// <returns></returns> public static Scene CornellBox() { var s = new Scene() { CameraOrigin = new Vector3(278, 274.4, -548), // -800 AspectRatio = 1.0 / 1.0, ImagePlaneWidth = 7 // 5.5 }; Shape el; // floor el = new Quad(556.0, 559.2 * 3, Transform.Translate(556.0 / 2, 0, 559.2 / 2).A(Transform.RotateX(-90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.White))); s.Elements.Add(el); // celing el = new Quad(556.0, 559.2 * 3, Transform.Translate(556.0 / 2, 548.8, 559.2 / 2).A(Transform.RotateX(90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.White))); s.Elements.Add(el); // back el = new Quad(556.0, 548.8, Transform.Translate(556.0 / 2, 548.8 / 2, 559.2).A(Transform.RotateX(180))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.White))); s.Elements.Add(el); // back2 el = new Quad(556.0, 548.8, Transform.Translate(556.0 / 2, 548.8 / 2, -550).A(Transform.RotateX(180))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.White))); s.Elements.Add(el); //double[] brdfs2 = ReadMerl.Read(@"D:\NRG seminarska\green-plastic.binary"); //right el = new Quad(559.2 * 3, 548.8, Transform.Translate(556.0, 548.8 / 2, 559.2 / 2).A(Transform.RotateY(90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Green))); //el.BSDF.Add(new Merl(brdfs2)); s.Elements.Add(el); //left el = new Quad(559.2 * 3, 548.8, Transform.Translate(0, 548.8 / 2, 559.2 / 2).A(Transform.RotateY(-90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Red))); s.Elements.Add(el); // luč // kvadratna luč s.Elements.Add(new DiffuseAreaLight(new Quad(170, 170, Transform.Translate(278, 548, 220).A(Transform.RotateX(90))), Spectrum.Create(1), 25)); s.Elements.Add(new DiffuseAreaLight(new Quad(170, 170, Transform.Translate(278, 548, -280).A(Transform.RotateX(90))), Spectrum.Create(1), 25)); //s.Elements.Add(new DiffuseAreaLight(new Disk(100, 0.1, Transform.Translate(278, 548, 280).A(Transform.RotateX(90))), Spectrum.Create(1), 20)); //s.Elements.Add(new DiffuseAreaLight(new Disk(100, 0.1, Transform.Translate(278, 548, 0).A(Transform.RotateX(90))), Spectrum.Create(1), 30)); //s.Elements.Add(new DiffuseAreaLight(new Disk(100, 0.1, Transform.Translate(278, 548, -280).A(Transform.RotateX(90))), Spectrum.Create(1), 20)); //s.Elements.Add(new DiffuseAreaLight(new Sphere(80, Transform.Translate(278, 548, 280).A(Transform.RotateX(90))), Spectrum.Create(1), 20)); //s.Elements.Add(new DiffuseAreaLight(new Sphere(80, Transform.Translate(278, 548, 280)), Spectrum.Create(1), 20)); //s.Elements.Add(new DiffuseAreaLight(new Sphere(60, Transform.Translate(278, 280, 300).A(Transform.RotateX(90))), Spectrum.Create(1), 20)); //s.Elements.Add(new DiffuseAreaLight(new Sphere(80, Transform.Translate(400, 80, 400).A(Transform.RotateX(90))), Spectrum.Create(1), 20)); //s.Elements.Add(new DiffuseAreaLight(new Sphere(1100, Transform.Translate(278, 280, 280).A(Transform.RotateX(90))), Spectrum.Create(1), 20)); double[] brdfs0 = ReadMerl.Read(@"D:\NRG seminarska\gold-metallic-paint.binary"); //double[] brdfs0 = ReadMerl.Read(@"D:\NRG seminarska\white-acrylic.binary"); //double[] brdfs0 = ReadMerl.Read(@"D:\NRG seminarska\white-diffuse-bball.binary"); //double[] brdfs0 = ReadMerl.Read(@"D:\NRG seminarska\white-fabric.binary"); //double[] brdfs0 = ReadMerl.Read(@"D:\NRG seminarska\white-fabric2.binary"); //double[] brdfs0 = ReadMerl.Read(@"D:\NRG seminarska\white-marble.binary"); //double[] brdfs0 = ReadMerl.Read(@"D:\NRG seminarska\white-paint.binary"); //double[] brdfs0 = ReadMerl.Read(@"D:\NRG seminarska\ss440.binary"); // modra krogla //el = new Sphere(100, Transform.Translate(150, 100, 420)); //el = new Sphere(130, Transform.Translate(180, 130, 400)); //el.BSDF.Add(new SpecularReflection(Spectrum.ZeroSpectrum.FromRGB(Color.White), 0, 0)); //el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Blue))); //el.BSDF.Add(new OrenNayar(Spectrum.ZeroSpectrum.FromRGB(Color.Blue), 10)); //el.BSDF.Add(new Merl(brdfs1)); //s.Elements.Add(el); //rumena krogla //el = new Sphere(130, Transform.Translate(400, 130, 230)); el = new Sphere(200, Transform.Translate(250, 200, 230)); //el.BSDF.Add(new SpecularReflection(Spectrum.ZeroSpectrum.FromRGB(Color.White),0,0)); //el.BSDF.Add(new SpecularReflection(Spectrum.ZeroSpectrum.FromRGB(Color.White),0.25,0.6)); //el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Yellow))); //el.BSDF.Add(new OrenNayar(Spectrum.ZeroSpectrum.FromRGB(Color.Yellow), 5)); el.BSDF.Add(new Merl(brdfs0)); //el.BSDF.Add(new SpecularReflection(Spectrum.ZeroSpectrum.FromRGB(Color.White), 1, 1.5)); s.Elements.Add(el); //el = new Sphere(60, Transform.Translate(180, 60, 100)); //el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Yellow))); //s.Elements.Add(el); return(s); }
public static Scene AllMerlInOne() { var s = new Scene() { CameraOrigin = new Vector3(278, 274.4, -548), // -800 AspectRatio = 1.0 / 1.0, ImagePlaneWidth = 5 // 5.5 }; Shape el; // floor el = new Quad(556.0, 559.2 * 2, Transform.Translate(556.0 / 2, 0, 559.2 / 2).A(Transform.RotateX(-90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.White))); s.Elements.Add(el); // celing el = new Quad(556.0, 559.2 * 2, Transform.Translate(556.0 / 2, 548.8, 559.2 / 2).A(Transform.RotateX(90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.White))); s.Elements.Add(el); // back el = new Quad(556.0, 548.8, Transform.Translate(556.0 / 2, 548.8 / 2, 559.2).A(Transform.RotateX(180))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.White))); s.Elements.Add(el); // back2 el = new Quad(556.0, 548.8, Transform.Translate(556.0 / 2, 548.8 / 2, -550).A(Transform.RotateX(180))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.White))); s.Elements.Add(el); // right el = new Quad(559.2 * 2, 548.8, Transform.Translate(556.0, 548.8 / 2, 559.2 / 2).A(Transform.RotateY(90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Green))); s.Elements.Add(el); // left el = new Quad(559.2 * 2, 548.8, Transform.Translate(0, 548.8 / 2, 559.2 / 2).A(Transform.RotateY(-90))); el.BSDF.Add(new Lambertian(Spectrum.ZeroSpectrum.FromRGB(Color.Red))); s.Elements.Add(el); // luč // kvadratna luč s.Elements.Add(new DiffuseAreaLight(new Quad(170, 170, Transform.Translate(278, 548, 200).A(Transform.RotateX(90))), Spectrum.Create(1), 31)); s.Elements.Add(new DiffuseAreaLight(new Quad(170, 170, Transform.Translate(278, 548, -280).A(Transform.RotateX(90))), Spectrum.Create(1), 35)); DirectoryInfo d = new DirectoryInfo(@"D:\NRG seminarska\"); FileInfo[] Files = d.GetFiles("*.binary"); //int xOff = 25; //int yOff = 25; //int countSpheres = 0; //foreach (FileInfo file in Files) //{ // double[] brdf0 = ReadMerl.Read(@"D:\NRG seminarska\" + file.Name); // el = new Sphere(25, Transform.Translate(xOff, yOff, 400)); // el.BSDF.Add(new Merl(brdf0)); // s.Elements.Add(el); // countSpheres++; // xOff += 52; // if (countSpheres % 10 == 0) // { // yOff += 52; // xOff = 25; // } // if (countSpheres == 49) // { // //break; // } //} //int xOff = 38; //int yOff = 38; //int countSpheres = 0; //foreach (FileInfo file in Files) //{ // //if (countSpheres < 49) { // // countSpheres++; // // continue; // //} // double[] brdf0 = ReadMerl.Read(@"D:\NRG seminarska\" + file.Name); // el = new Sphere(36, Transform.Translate(xOff, yOff, 480)); // el.BSDF.Add(new Merl(brdf0)); // s.Elements.Add(el); // countSpheres++; // xOff += 77; // if (countSpheres % 7 == 0) // { // yOff += 77; // xOff = 38; // } // if (countSpheres == 49) //49 //98 // { // break; // } //} int xOff = 55; int yOff = 55; int countSpheres = 0; foreach (FileInfo file in Files) { double[] brdf0 = ReadMerl.Read(@"D:\NRG seminarska\" + file.Name); el = new Sphere(50, Transform.Translate(xOff, yOff, 480)); el.BSDF.Add(new Merl(brdf0)); el.BSDF.Add(new SpecularReflection(Spectrum.ZeroSpectrum.FromRGB(Color.White), 1, 1.5)); s.Elements.Add(el); countSpheres++; xOff += 105; if (countSpheres % 5 == 0) { yOff += 105; xOff = 55; } if (countSpheres == 25) { break; } } return(s); }
public void Render(Scene s, CancellationToken token) { var integrator = new PathTracer(); // Use ParallelOptions instance to store the CancellationToken ParallelOptions po = new ParallelOptions() { MaxDegreeOfParallelism = 8, CancellationToken = token }; try { //DirectoryInfo d = new DirectoryInfo(@"D:\NRG seminarska\"); //FileInfo[] Files = d.GetFiles("*.binary"); //foreach (FileInfo file in Files) //{ //Scene.brdfFileName = file.Name; //Console.WriteLine(file.Name); //while (totalSamples < maxTotalSamples) while (true) { var samples = SamplePointsOnImagePlane(s, 1); Parallel.ForEach(samples, po, samp => { // if cancel requested from GUI, cancel token.ThrowIfCancellationRequested(); var rayTo = new Vector3(samp.X - s.ImagePlaneWidth / 2, samp.Y - s.ImagePlaneHeight / 2 + s.ImagePlaneVerticalOffset, s.ImagePlaneDistance); // ray through point Ray r = new Ray(s.CameraOrigin, rayTo); // evaluate radiance Spectrum L = integrator.Li(r, s); // add radiance to image AddToImage(samp, L, s); }); } //Neki: // try // { // finalRgbImage.Save(@"D:\NRG seminarska\" + DateTime.Now.ToString().Replace("/", "-").Replace(":", "-").Replace(" ", "_") + "_" + file.Name.Replace(".binary", "") + ".png", ImageFormat.Png); // } // catch (Exception) // { // Thread.Sleep(1); // goto Neki; // } // s = Scene.CornellBox(); // finalImageSum = new Spectrum[pixelWidth, pixelHeight]; // finalImage = new Spectrum[pixelWidth, pixelHeight]; // finalRgbImage = new Bitmap(160, (int)Math.Round(160 / s.AspectRatio), PixelFormat.Format24bppRgb); // pixelWeights = new double[pixelWidth, pixelHeight]; // bmp = finalRgbImage; // totalSamples = 0; //bmp = b; //} } catch (OperationCanceledException) { } catch (Exception e) { Console.WriteLine(e); } }
public RectangleLight(Quad q, Spectrum l, double intensity = 1, bool onesided = true) { quad = q; Lemit = l * intensity; this.onesided = onesided; }