public BvhNode(List <Hitable> list, double time0, double time1) { int axis = (int)(FastRandom.RandomDouble() * 3); list.Sort(compareHitable(axis)); if (list.Count == 1) { left = right = list[0]; } else if (list.Count == 2) { left = list[0]; right = list[1]; } else { left = new BvhNode(list.GetRange(0, list.Count / 2), time0, time1); right = new BvhNode(list.GetRange(list.Count / 2, list.Count - list.Count / 2), time0, time1); } AxisAlignedBoundingBox boxLeft, boxRight; if (!left.BoundingBox(time0, time1, out boxLeft) || !right.BoundingBox(time0, time1, out boxRight)) { throw new Exception("No Bounding Box in BvhNode Constructor."); } box = AxisAlignedBoundingBox.SurroundingBox(boxLeft, boxRight); }
private void Permute(int[] p, int n) { for (int i = n - 1; i > 0; i--) { int target = (int)(FastRandom.RandomDouble() * (i + 1)); int tmp = p[i]; p[i] = p[target]; p[target] = tmp; } return; }
private Vec3[] PerlinGenerate() { Vec3[] p = new Vec3[256]; for (int i = 0; i < 256; i++) { p[i] = Vec3.UnitVector(new Vec3(-1 + 2 * FastRandom.RandomDouble(), -1 + 2 * FastRandom.RandomDouble(), -1 + 2 * FastRandom.RandomDouble())); } return(p); }
public override bool Scatter(Ray rIn, HitRecord rec, out Vec3 attenuation, out Ray scattered) { Vec3 outwardNormal = new Vec3(); Vec3 reflected = Vec3.Reflect(rIn.Direction(), rec.Normal); double niOverNt; attenuation = new Vec3(1.0, 1.0, 1.0); Vec3 refracted = new Vec3(); double reflectProb; double cosine; if (Vec3.Dot(rIn.Direction(), rec.Normal) > 0) { outwardNormal = -rec.Normal; niOverNt = _refIndex; cosine = _refIndex * Vec3.Dot(rIn.Direction(), rec.Normal) / rIn.Direction().Length(); } else { outwardNormal = rec.Normal; niOverNt = 1.0 / _refIndex; cosine = -Vec3.Dot(rIn.Direction(), rec.Normal) / rIn.Direction().Length(); } if (Vec3.Refract(rIn.Direction(), outwardNormal, niOverNt, out refracted)) { reflectProb = Schlick(cosine, _refIndex); } else { reflectProb = 1.0; } if (FastRandom.RandomDouble() < reflectProb) { scattered = new Ray(rec.P, reflected, rIn.Time()); } else { scattered = new Ray(rec.P, refracted, rIn.Time()); } return(true); }
public override Hitable GetObjects() { List <Hitable> list = new List <Hitable>(); var checker = new CheckerTexture(new ConstantTexture(new Vec3(0.2, 0.3, 0.1)), new ConstantTexture(new Vec3(0.9, 0.9, 0.9))); list.Add(new Sphere(new Vec3(0.0, -1000.0, 0.0), 1000, new Lambertian(checker))); for (int a = -11; a < 11; a++) { for (int b = -11; b < 11; b++) { double chooseMaterial = FastRandom.RandomDouble(); Vec3 center = new Vec3(a + 0.9 * FastRandom.RandomDouble(), 0.2, b + 0.9 * FastRandom.RandomDouble()); if ((center - new Vec3(4.0, 0.2, 0.0)).Length() > 0.9) { if (chooseMaterial < 0.8) // diffuse { list.Add(new MovingSphere(center, center + new Vec3(0.0, 0.5 * FastRandom.RandomDouble(), 0.0), 0.0, 1.0, 0.2, new Lambertian(new ConstantTexture(new Vec3(FastRandom.RandomDouble() * FastRandom.RandomDouble(), FastRandom.RandomDouble() * FastRandom.RandomDouble(), (FastRandom.RandomDouble() * FastRandom.RandomDouble())))))); } else if (chooseMaterial < 0.95) // metal { list.Add(new Sphere(center, 0.2, new Metal(new Vec3(0.5 * (1.0 + FastRandom.RandomDouble()), 0.5 * (1.0 + FastRandom.RandomDouble()), 0.5 * (1.0 + FastRandom.RandomDouble())), 0.5 * FastRandom.RandomDouble()))); } else // dielectric { list.Add(new Sphere(center, 0.2, new Dielectric(1.5))); } } } } list.Add(new Sphere(new Vec3(0.0, 1.0, 0.0), 1.0, new Dielectric(1.5))); list.Add(new Sphere(new Vec3(-4.0, 1.0, 0.0), 1.0, new Lambertian(new ConstantTexture(new Vec3(0.4, 0.2, 0.1))))); list.Add(new Sphere(new Vec3(4.0, 1.0, 0.0), 1.0, new Metal(new Vec3(0.7, 0.6, 0.5), 0.0))); return((Hitable) new BvhNode(list, 0.0, 1.0)); }
static void Main(string[] args) { // Seed RNG FastRandom.Initialize((uint)new Random().Next()); string homePath = (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX) ? Environment.GetEnvironmentVariable("HOME") : Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%"); var outputFileName = Path.Combine(new string[] { homePath, "output.jpg" }); var nx = 600; // Horizontal resolution var ny = 400; // Vertical resolution var ns = 150; // Antialising samples per pixel Console.WriteLine($"Width:\t{nx}"); Console.WriteLine($"Height:\t{ny}"); Console.WriteLine($"Antialiasing:\t{ns}"); Console.WriteLine(); var scene = new Scenes.CornellBox(); var world = scene.GetObjects(); var cam = scene.GetCamera((double)nx / (double)ny); byte[] outputBytes = new byte[4 * nx * ny]; Console.WriteLine("Rendering..."); UpdateProgress(ny, 0); var linesRendered = 0; Parallel.For(0, ny, j => { for (int i = 0; i < nx; i++) { Vec3 col = new Vec3(0.0, 0.0, 0.0); for (int s = 0; s < ns; s++) { double u = (i + FastRandom.RandomDouble()) / nx; double v = (j + FastRandom.RandomDouble()) / ny; Ray r = cam.GetRay(u, v); col += Color(r, world, 0); } col /= ns; col = new Vec3(Math.Sqrt(col[0]), Math.Sqrt(col[1]), Math.Sqrt(col[2])); outputBytes[4 * ((ny - 1 - j) * nx) + (4 * i)] = (byte)(255.9 * col[0]); outputBytes[4 * ((ny - 1 - j) * nx) + (4 * i) + 1] = (byte)(255.9 * col[1]); outputBytes[4 * ((ny - 1 - j) * nx) + (4 * i) + 2] = (byte)(255.9 * col[2]); outputBytes[4 * ((ny - 1 - j) * nx) + (4 * i) + 3] = 255; } linesRendered++; UpdateProgress(ny, linesRendered); }); Console.WriteLine("\nRendering completed, writing to file..."); var outputImg = Image.LoadPixelData <Byte4>(outputBytes, nx, ny); outputImg.Save(outputFileName); Console.WriteLine("Saving completed, press any key to exit."); Console.ReadKey(); }