public bool Scatter(Ray r_in, Hit_Record rec, out Vector3 attenuation, out Ray scattered) { attenuation = Vector3.One; float etai_over_etat = (rec.Front_face) ? (1.0f / Ref_idx) : (Ref_idx); Vector3 unit_direction = Vector3.Normalize(r_in.Direction); float cos_theta = Math.Min(Vector3.Dot(-unit_direction, rec.Normal), 1.0f); float sin_theta = (float)Math.Sqrt(1.0f - cos_theta * cos_theta); if (etai_over_etat * sin_theta > 1.0f) { Vector3 reflected = Helpers.Reflect(unit_direction, rec.Normal); scattered = new Ray(rec.P, reflected); return(true); } float reflect_prob = Helpers.Schlick(cos_theta, etai_over_etat); if (Helpers.random.NextDouble() < reflect_prob) { Vector3 reflected = Helpers.Reflect(unit_direction, rec.Normal); scattered = new Ray(rec.P, reflected); return(true); } Vector3 refracted = Helpers.Refract(unit_direction, rec.Normal, etai_over_etat); scattered = new Ray(rec.P, refracted); return(true); }
static Vector3 Ray_color(Ray r, HitTable world, int depth) { Hit_Record rec = default; // If we've exceeded the ray bounce limit, no more light is gathered. if (depth <= 0) { return(Vector3.Zero); } if (world.Hit(r, 0.001f, Helpers.Infinity, ref rec)) { Ray scattered; Vector3 attenuation; if (rec.Mat_ptr.Scatter(r, rec, out attenuation, out scattered)) { return(attenuation * Ray_color(scattered, world, depth - 1)); } return(Vector3.Zero); } Vector3 unit_direction = Vector3.Normalize(r.Direction); var t = 0.5f * (unit_direction.Y + 1.0f); return((1.0f - t) * new Vector3(1.0f, 1.0f, 1.0f) + t * new Vector3(0.5f, 0.7f, 1.0f)); }
public bool Hit(Ray r, float t_min, float t_max, ref Hit_Record rec) { Vector3 oc = r.Origin - this.Center; float a = r.Direction.LengthSquared(); float half_b = Vector3.Dot(oc, r.Direction); float c = oc.LengthSquared() - this.Radius * this.Radius; float discriminant = half_b * half_b - a * c; if (discriminant > 0) { float root = (float)Math.Sqrt(discriminant); float temp = (-half_b - root) / a; if (temp < t_max && temp > t_min) { rec.T = temp; rec.P = r.At(rec.T); Vector3 outward_normal = (rec.P - this.Center) / this.Radius; rec.Set_Face_Normal(r, outward_normal); rec.Mat_ptr = Material; return(true); } temp = (-half_b + root) / a; if (temp < t_max && temp > t_min) { rec.T = temp; rec.P = r.At(rec.T); Vector3 outward_normal = (rec.P - this.Center) / this.Radius; rec.Set_Face_Normal(r, outward_normal); rec.Mat_ptr = Material; return(true); } } return(false); }
public bool Scatter(Ray r_in, Hit_Record rec, out Vector3 attenuation, out Ray scattered) { Vector3 scatter_direction = rec.Normal + Helpers.Random_unit_Vector(); scattered = new Ray(rec.P, scatter_direction); attenuation = this.Albedo; return(true); }
public bool Scatter(Ray r_in, Hit_Record rec, out Vector3 attenuation, out Ray scattered) { Vector3 unit_vector = Vector3.Normalize(r_in.Direction); Vector3 reflected = Helpers.Reflect(unit_vector, rec.Normal); scattered = new Ray(rec.P, reflected + fuzz * Helpers.Random_in_unit_sphere()); attenuation = this.Albedo; return(Vector3.Dot(scattered.Direction, rec.Normal) > 0); }
public bool Hit(Ray r, float t_min, float t_max, ref Hit_Record rec) { Hit_Record temp_rec = default; bool hit_anything = false; float closest_so_far = t_max; foreach (var o in this.Objects) { if (o.Hit(r, t_min, closest_so_far, ref temp_rec)) { hit_anything = true; closest_so_far = temp_rec.T; rec = temp_rec; } } return(hit_anything); }