public XZTriangle(float x0, float x1, float x2, float z0, float z1, float z2, float k, Material mat) { this.x0 = x0; this.x1 = x1; this.z0 = z0; this.z1 = z1; this.x2 = x2; this.z2 = z2; this.k = k; this.mat = mat; float xMin = Mathf.Min(Mathf.Min(x0, x1), x2); float xMax = Mathf.Max(Mathf.Max(x0, x1), x2); float zMin = Mathf.Min(Mathf.Min(z0, z1), z2); float zMax = Mathf.Max(Mathf.Max(z0, z1), z2); rect = new XZRect(xMin, xMax, zMin, zMax, k, mat); }
private void InitScene() { int width = 512; int height = 512; bool isSky = false; Vector3D lookFrom = new Vector3D(278, 278, -800); Vector3D lookAt = new Vector3D(278, 278, 0); float diskToFocus = 10; float aperture = 0; float vfov = 40; Camera camera = new Camera(lookFrom, lookAt, new Vector3D(0, 1, 0), vfov, (float)width / (float)height, aperture, diskToFocus, 0, 1); List <Hitable> list = new List <Hitable>(); Material red = new Lambertian(new ConstantTexture(new Vector3D(0.65f, 0.05f, 0.05f))); Material white = new Lambertian(new ConstantTexture(new Vector3D(0.73f, 0.73f, 0.73f))); Material green = new Lambertian(new ConstantTexture(new Vector3D(0.12f, 0.45f, 0.15f))); Material light = new DiffuseLight(new ConstantTexture(new Vector3D(7, 7, 7))); list.Add(new FlipNormals(new XZTriangle(113, 443, 278, 127, 127, 432, 554, light))); list.Add(new FlipNormals(new YZRect(0, 555, 0, 555, 555, green))); list.Add(new YZRect(0, 555, 0, 555, 0, red)); list.Add(new FlipNormals(new XZRect(0, 555, 0, 555, 555, white))); list.Add(new XZRect(0, 555, 0, 555, 0, white)); list.Add(new FlipNormals(new XYRect(0, 555, 0, 555, 555, white))); Hitable b1 = new Translate(new RotateY(new Box(new Vector3D(0, 0, 0), new Vector3D(165, 165, 165), white), -18), new Vector3D(130, 0, 65)); Hitable b2 = new Translate(new RotateY(new Box(new Vector3D(0, 0, 0), new Vector3D(165, 330, 165), white), 15), new Vector3D(265, 0, 295)); list.Add(new ConstantMedium(b1, 0.01f, new ConstantTexture(new Vector3D(1, 1, 1)))); list.Add(new ConstantMedium(b2, 0.01f, new ConstantTexture(new Vector3D(0, 0, 0)))); BVHNode b = new BVHNode(list, list.Count, 0, 1); HitableList world = new HitableList(); world.list.Add(b); HitableList lightShapeList = new HitableList(); Hitable lightShape = new XZRect(113, 443, 127, 432, 554, null); lightShapeList.list.Add(lightShape); scene = new Scene(width, height, world, isSky, camera, 0.5f, true, lightShapeList); }
private void LinearScanner(object o) { ScannerCofig config = (ScannerCofig)o; for (int j = 0; j < config.height; j++) { for (int i = 0; i < config.width; i++) { Vector3D color = new Vector3D(0, 0, 0); float u = (float)(i + Mathf.Randomfloat()) / (float)width; float v = 1 - (float)(j + Mathf.Randomfloat()) / (float)height; Ray ray = camera.GetRay(u, v); Hitable lightShape = new XZRect(213, 343, 227, 332, 554, new Lambertian()); color = GetColor(ray, world, lightShape, 0); // color = new Vector3D(Mathf.Sqrt(color.X), Mathf.Sqrt(color.Y), Mathf.Sqrt(color.Z));//这里不应进行伽马校正 SetPixel(i, j, color); } } }
private Vector3D GetColor(Ray r, HitableList world, int depth) { HitRecord rec; /*这里的0.001不能改为0,当tmin设0的时候会导致,遍历hitlist时候,ray的t求解出来是0, * hit的时候全走了else,导致递归到50层的时候,最后return的是0,* attenuation结果还是0。 * 距离越远,散射用到random_in_unit_sphere生成的ray误差越大 */ if (world.Hit(r, 0.001f, float.MaxValue, out rec)) { Ray scattered; Vector3D emitted = rec.matPtr.Emitted(r, rec, rec.u, rec.v, rec.p); Vector3D albedo; float pdfVal; if (depth < 50 && rec.matPtr.Scatter(r, rec, out albedo, out scattered, out pdfVal)) { Hitable lightSphape = new XZRect(213, 343, 227, 332, 554, new Lambertian()); HitablePDF p0 = new HitablePDF(lightSphape, rec.p); CosinePDF p1 = new CosinePDF(rec.normal); MixturePDF p = new MixturePDF(p0, p1); scattered = new Ray(rec.p, p.Generate(), r.Time); pdfVal = p.Value(scattered.Direction); Vector3D color = GetColor(scattered, world, depth + 1); //每次光线衰减之后深度加一 return(emitted + rec.matPtr.ScatteringPDF(r, rec, scattered) * new Vector3D(albedo.X * color.X, albedo.Y * color.Y, albedo.Z * color.Z) / pdfVal); } else { return(emitted); } } else { //Vector3D unitDirection = r.Direction.UnitVector(); //float t = 0.5f * (unitDirection.Y + 1f); //return (1 - t) * new Vector3D(1, 1, 1) + t * new Vector3D(0.5f, 0.7f, 1); return(new Vector3D(0, 0, 0)); } }
private void LinearScanner(object o) { ScannerCofig config = (ScannerCofig)o; Hitable lightShape = new XZRect(213, 343, 227, 332, 554, null); Hitable glassSphere = new Sphere(new Vector3D(190, 90, 190), 90, null); for (int j = 0; j < config.height; j++) { for (int i = 0; i < config.width; i++) { Vector3D color = new Vector3D(0, 0, 0); float u = (float)(i + Mathf.Randomfloat()) / (float)width; float v = 1 - (float)(j + Mathf.Randomfloat()) / (float)height; Ray ray = camera.GetRay(u, v); List <Hitable> a = new List <Hitable>(); a.Add(lightShape); a.Add(glassSphere); HitableList hitableList = new HitableList(a); color = DeNaN(GetColor(ray, world, hitableList, 0)); color = new Vector3D(Mathf.Sqrt(color.X), Mathf.Sqrt(color.Y), Mathf.Sqrt(color.Z)); SetPixel(i, j, color); } } }
private void InitScene() { int width = 512; int height = 512; bool isSky = false; Vector3D lookFrom = new Vector3D(500, 300, -600); Vector3D lookAt = new Vector3D(278, 278, 0); float diskToFocus = 10; float aperture = 0; float vfov = 40; Camera camera = new Camera(lookFrom, lookAt, new Vector3D(0, 1, 0), vfov, (float)width / (float)height, aperture, diskToFocus, 0, 1); List <Hitable> list = new List <Hitable>(); List <Hitable> boxList = new List <Hitable>(); List <Hitable> boxList2 = new List <Hitable>(); int nb = 20; Material white = new Lambertian(new ConstantTexture(new Vector3D(0.73f, 0.73f, 0.73f))); Material ground = new Lambertian(new ConstantTexture(new Vector3D(0.48f, 0.83f, 0.53f))); Material light = new DiffuseLight(new ConstantTexture(new Vector3D(7, 7, 7))); for (int i = 0; i < nb; i++) { for (int j = 0; j < nb; j++) { float w = 100; float x0 = -1000 + i * w; float z0 = -1000 + j * w; float y0 = 0; float x1 = x0 + w; float y1 = 100 * (Mathf.Randomfloat() + 0.01f); float z1 = z0 + w; boxList.Add(new Box(new Vector3D(x0, y0, z0), new Vector3D(x1, y1, z1), ground)); } } list.Add(new BVHNode(boxList, boxList.Count, 0, 1)); list.Add(new FlipNormals(new XZRect(123, 423, 147, 412, 554, light))); Vector3D center = new Vector3D(400, 400, 200); list.Add(new MovingSphere(center, center + new Vector3D(30, 0, 0), 0, 1, 50, new Lambertian(new ConstantTexture(new Vector3D(0.7f, 0.3f, 0.1f))))); list.Add(new Sphere(new Vector3D(260, 150, 45), 50, new Dielectric(1.5f))); list.Add(new Sphere(new Vector3D(0, 150, 145), 50, new Metal( new Vector3D(0.8f, 0.8f, 0.9f), 10))); Hitable boundary = new Sphere(new Vector3D(360, 150, 145), 70, new Dielectric(1.5f)); list.Add(boundary); list.Add(new ConstantMedium(boundary, 0.2f, new ConstantTexture(new Vector3D(0.2f, 0.4f, 0.9f)))); boundary = new Sphere(new Vector3D(0, 0, 0), 5000, new Dielectric(1.5f)); list.Add(new ConstantMedium(boundary, 0.0001f, new ConstantTexture(new Vector3D(1, 1, 1)))); Material emat = new Lambertian(new Imagetexture("Earth.jpg")); list.Add(new Sphere(new Vector3D(400, 200, 400), 100, emat)); Texture pertext = new NoiseTexture(1f); list.Add(new Sphere(new Vector3D(220, 280, 300), 80, new Lambertian(pertext))); int ns = 1000; for (int j = 0; j < ns; j++) { boxList2.Add(new Sphere(new Vector3D(165 * Mathf.Randomfloat(), 165 * Mathf.Randomfloat(), 165 * Mathf.Randomfloat()), 10, white)); } list.Add(new Translate(new RotateY(new BVHNode(boxList2, ns, 0, 1), 15), new Vector3D(-100, 270, 395))); BVHNode b = new BVHNode(list, list.Count, 0, 1); HitableList world = new HitableList(); world.list.Add(b); HitableList lightShapeList = new HitableList(); Hitable lightShape = new XZRect(123, 423, 147, 412, 554, null); lightShapeList.list.Add(lightShape); scene = new Scene(width, height, world, isSky, camera, 0.5f, false, lightShapeList); }