// if no object is hit, draw a gradient static Vector3 color(Ray r, Hitable world, int depth) { hit_record rec = new hit_record(); // see if an object is hit if (world.hit(r, 0.001f, float.MaxValue, ref rec)) { // shade the indicated point Ray scattered = new Ray(); Vector3 attenuation = new Vector3(); if (depth < 50 && rec.mat.scatter(r, rec, ref attenuation, ref scattered)) { return(attenuation * color(scattered, world, depth + 1)); } else { // reached our max depth, don't render any further return(new Vector3()); } } else { // no object hit, draw the background Vector3 unit_dir = r.direction().unit_vector(); float t = 0.5f * (unit_dir.y() + 1.0f); return((new Vector3(1.0f, 1.0f, 1.0f)) * (1.0f - t) + (new Vector3(0.5f, 0.7f, 1.0f) * t)); } }
public BVH_Node(List <Hitable> l, float t0, float t1) { // randomly select an axis to sort child nodes by int axis = Utils.rnd.Next(3); if (axis == 0) { //x l.Sort(Utils.hitable_box_compare_x); } else if (axis == 1) { //y l.Sort(Utils.hitable_box_compare_y); } else { //z l.Sort(Utils.hitable_box_compare_z); } // build the tree if (l.Count == 1) { left = l [0]; right = l [0]; } else if (l.Count == 2) { left = l [0]; right = l [1]; } else { List <Hitable> l_hitables = l.GetRange(0, (int)Math.Floor(l.Count / 2.0f) + 1); List <Hitable> r_hitables = l.GetRange(l_hitables.Count, l.Count - l_hitables.Count); left = new BVH_Node(l_hitables, t0, t1); right = new BVH_Node(r_hitables, t0, t1); } AABB box_left = new AABB(); AABB box_right = new AABB(); // ensure that there is a possible bounding box before continuing if (!left.bounding_box(t0, t1, ref box_left) || !right.bounding_box(t0, t1, ref box_right)) { Console.Error.WriteLine("No possible bounding box in BVH constructor!"); List <Hitable> l_hitables = l.GetRange(0, (int)Math.Floor(l.Count / 2.0f) + 1); List <Hitable> r_hitables = l.GetRange(l_hitables.Count, l.Count - l_hitables.Count); Console.Error.WriteLine(l_hitables.Count + " " + r_hitables.Count); } box = AABB.surrounding_box(box_left, box_right); }
// used for comparing bounding boxes of two hitables public static int hitable_box_compare_x(Hitable a, Hitable b) { AABB box_left = new AABB(); AABB box_right = new AABB(); if (!a.bounding_box(0.0f, 0.0f, ref box_left) || !b.bounding_box(0.0f, 0.0f, ref box_right)) { Console.Error.WriteLine("No possible bounding box during x comparison"); } if (box_left.min().x() - box_right.min().x() < 0.0f) { return(-1); } else { return(1); } }
private static Vec3 Color(Ray r, Hitable world, int depth) { HitRecord rec = new HitRecord(); if (world.Hit(r, 0.001, double.MaxValue, out rec)) { Ray scattered = new Ray(); Vec3 attenuation = new Vec3(); Vec3 emitted = rec.Material.emitted(rec.U, rec.V, rec.P); if (depth < 50 && rec.Material.Scatter(r, rec, out attenuation, out scattered)) { return(emitted + attenuation * Color(scattered, world, depth + 1)); } else { return(emitted); } } else { return(new Vec3(0.0, 0.0, 0.0)); } }