public override zwischenSpeicher scatter(ray r_in, hit_record rec, Vektor attenuation, ray scattered) { zwischenSpeicher zw = new zwischenSpeicher(); attenuation = new Vektor(1, 1, 1); double refraction_ratio = rec.front_face ? (1 / ir) : ir; Vektor unit_direction = Vektor.unit_Vektor(r_in.Direction); double cos_theta = Math.Min(Vektor.dot(unit_direction * -1, rec.normal), 1); double sin_theta = Math.Sqrt(1 - cos_theta * cos_theta); bool cannot_refract = refraction_ratio * sin_theta > 1; Vektor direction; if (cannot_refract) { direction = Vektor.reflect(unit_direction, rec.normal); } else { direction = Vektor.refract(unit_direction, rec.normal, refraction_ratio); } scattered = new ray(rec.p, direction); zw.attenuation = attenuation; zw.scattered = scattered; zw.IsTrue = true; return(zw); }
public ray get_ray(double s, double t) { Vektor rd = lens_radius * Vektor.random_in_unit_disk(); Vektor offset = u * rd.X + v * rd.Y; return(new ray(origin + offset, lower_left_corner + s * horizontal + t * vertical - origin - offset)); }
public static Vektor ray_color(ray r, hittable world, int depth) { hit_record rec = new hit_record(); if (depth <= 0) { return(new Vektor(0, 0, 0)); } zwischenSpeicher zw = world.Hit(r, 0.0001, Mathe.infinity, rec); if (zw.IsTrue) { rec = zw.rec; ray scattered = new ray(); Vektor attenuation = new Vektor(); zwischenSpeicher zw1 = rec.mat_ptr.scatter(r, rec, attenuation, scattered); if (zw1.IsTrue) { attenuation = zw1.attenuation; scattered = zw1.scattered; return(attenuation * ray_color(scattered, world, depth - 1)); } return(new Vektor(0, 0, 0)); } Vektor unit_direction = Vektor.unit_Vektor(r.Direction); var t = 0.5 * (unit_direction.Y + 1); Vektor col = (1 - t) * new Vektor(1, 1, 1) + t * new Vektor(0.5, 0.7, 1); return(col); }
public static Vektor operator *(double d2, Vektor v1) { Vektor v2 = new Vektor(d2, d2, d2); return(new Vektor(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z)); }
public static Vektor refract(Vektor uv, Vektor n, double etai_over_etat) { var cos_theta = Math.Min(Vektor.dot(uv * -1, n), 1); Vektor r_out_perp = etai_over_etat * (uv + cos_theta * n); Vektor r_out_parallel = -Math.Sqrt(Math.Abs(1 - r_out_perp.length_squared())) * n; return(r_out_perp + r_out_parallel); }
public static Vektor operator /(Vektor v1, double d2) { Vektor v2 = new Vektor(d2, d2, d2); return(new Vektor(v1.X / v2.X, v1.Y / v2.Y, v1.Z / v2.Z)); }
public static bool operator <=(Vektor v1, double d2) { Vektor v2 = new Vektor(d2, d2, d2); if (v1 < v2 || v1 == v2) { return(true); } return(false); }
public static bool operator !=(Vektor v1, double d2) { Vektor v2 = new Vektor(d2, d2, d2); if (v1.X != v2.X && v1.Y != v2.Y && v1.Z != v2.Z) { return(true); } return(false); }
public static Vektor random_in_unit_disk() { while (true) { var p = new Vektor(Mathe.random_1Tom1(), Mathe.random_1Tom1(), 0); if (p.length_squared() >= 1) { continue; } return(p); } }
public static Vektor random_in_unit_sphere() { while (true) { var p = Vektor.random(); if (p.length_squared() >= 1) { continue; } return(p); } }
public static Color toColor(Vektor pixel_color, int samples_per_pixel) { var r = pixel_color.X; var g = pixel_color.Y; var b = pixel_color.Z; var scale = (double)1 / (double)samples_per_pixel; r = Math.Sqrt(scale * r); g = Math.Sqrt(scale * g); b = Math.Sqrt(scale * b); return(Color.FromArgb(Convert.ToInt32(255 * Mathe.clamp(r, 0, 0.999)), Convert.ToInt32(255 * Mathe.clamp(g, 0, 0.999)), Convert.ToInt32(255 * Mathe.clamp(b, 0, 0.999)))); }
public static double hit_sphere(Vektor center, double radius, ray r) { Vektor oc = r.Origin - center; var a = r.Direction.length_squared(); var half_b = Vektor.dot(oc, r.Direction); var c = oc.length_squared() - radius * radius; var discriminant = half_b * half_b - a * c; if (discriminant < 0) { return(-1); } else { return((-half_b - Math.Sqrt(discriminant)) / a); } }
public Camera(Vektor lookfrom, Vektor lookat, Vektor vup, double vfov, double aspect_ratio, double aperture, double focus_dist) { var theta = Mathe.ToRad(vfov); var h = Math.Tan(theta / 2); var viewport_height = 2 * h; var viewport_width = aspect_ratio * viewport_height; w = Vektor.unit_Vektor(lookfrom - lookat); u = Vektor.unit_Vektor(Vektor.cross(vup, w)); v = Vektor.cross(w, u); origin = lookfrom; horizontal = focus_dist * viewport_width * u; vertical = focus_dist * viewport_height * v; lower_left_corner = origin - horizontal / 2 - vertical / 2 - focus_dist * w; lens_radius = aperture / 2; }
public override zwischenSpeicher Hit(ray r, double t_min, double t_max, hit_record rec) { zwischenSpeicher zw = new zwischenSpeicher(); Vektor oc = r.Origin - center; var a = r.Direction.length_squared(); var half_b = Vektor.dot(oc, r.Direction); var c = oc.length_squared() - radius * radius; var discriminant = half_b * half_b - a * c; if (discriminant < 0) { zw.IsTrue = false; return(zw); } var sqrtd = Math.Sqrt(discriminant); var root = (-half_b - sqrtd) / a; if (root < t_min || t_max < root) { root = (-half_b + sqrtd) / a; if (root < t_min || t_max < root) { zw.IsTrue = false; return(zw); } } rec.t = root; rec.p = r.at(rec.t); Vektor outward_normal = (rec.p - center) / radius; rec.set_face_normal(r, outward_normal); rec.mat_ptr = mat_ptr; zw.rec = rec; zw.IsTrue = true; return(zw); }
public static double dot(Vektor v, Vektor v1) { return(v.X * v1.X + v.Y * v1.Y + v.Z * v1.Z); }
public static Vektor reflect(Vektor v, Vektor n) { return(v - 2 * dot(v, n) * n); }
public static Vektor unit_Vektor(Vektor v) { return(v / v.length()); }
public static Vektor cross(Vektor u, Vektor v) { return(new Vektor(u.Y * v.Z - u.Z * v.Y, u.Z * v.X - u.X * v.Z, u.X * v.Y - u.Y * v.X)); }
public ray(Vektor origin, Vektor direction) { Origin = origin; Direction = direction; }
public MainWindow() { InitializeComponent(); const int image_width = 400; const int image_height = 236; double aspect_ratio = (double)image_width / (double)image_height; const int samples_per_pixel = 10; const int max_depth = 50; //World var world = new hittable_list(); var material = new Metal(new Vektor(.7, .7, .7), 0.7); var material1 = new Metal(new Vektor(1, 0.32, 0.36), 0); var material2 = new Metal(new Vektor(0.90, 0.76, 0.46), 0); var material3 = new Metal(new Vektor(0.65, 0.77, 0.97), 0); var material4 = new Metal(new Vektor(0.90, 0.90, 0.90), 0); world.Add(new sphere(new Vektor(0.0, -10004, -20), 10000, material)); world.Add(new sphere(new Vektor(0, 0, -20), 4, material1)); world.Add(new sphere(new Vektor(5, -1, -15), 2, material2)); world.Add(new sphere(new Vektor(5, 0, -25), 3, material3)); world.Add(new sphere(new Vektor(-5.5, 0, -15), 3, material4)); //Camera Vektor lookfrom = new Vektor(0, 0, 0); Vektor lookat = new Vektor(0, 0, -1); Vektor vup = new Vektor(0, 1, 0); var dist_to_focus = 10; var aperture = 0.1; Camera cam = new Camera(lookfrom, lookat, vup, 50, aspect_ratio, aperture, dist_to_focus); Vektor[,] vArr = new Vektor[image_height, image_width]; Bitmap bmp = new Bitmap(image_width, image_height); Parallel.For(0, image_height, j => { for (int i = 0; i < image_width; i++) { Vektor pixel_color = new Vektor(0, 0, 0); for (int s = 0; s < samples_per_pixel; s++) { var u = ((double)i + Mathe.random_double()) / (image_width - 1); var v = ((double)j + Mathe.random_double()) / (image_height - 1); ray r = cam.get_ray(u, v); pixel_color += ray.ray_color(r, world, max_depth); } vArr[j, i] = pixel_color; } }); for (int j = 0; j < image_height; j++) { for (int i = 0; i < image_width; i++) { bmp.SetPixel(i, (j - (image_height - 1)) * -1, Vektor.toColor(vArr[j, i], samples_per_pixel)); } } image.Source = BitmapToImageSource(bmp); }
public sphere(Vektor cen, double r, material m) { center = cen; radius = r; mat_ptr = m; }