public override bool hit(Ray r, float t_min, float t_max, ref hit_record rec) { Vector3 oc = r.origin() - center(r._time); float a = Vector3.dot(r.direction(), r.direction()); float b = 2.0f * Vector3.dot(oc, r.direction()); float c = Vector3.dot(oc, oc) - radius * radius; float discriminant = b * b - 4 * a * c; if (discriminant > 0) { // update the hit_record to pass the information back to the calling object float temp = (-b - (float)Math.Sqrt(b * b - 4 * a * c)) / (2 * a); // check the roots if (temp < t_max && temp > t_min) { rec.t = temp; rec.p = r.point(rec.t); rec.normal = (rec.p - center(r._time)) / radius; rec.mat = material; return(true); } temp = (-b + (float)Math.Sqrt(b * b - 4 * a * c)) / (2 * a); if (temp < t_max && temp > t_min) { rec.t = temp; rec.p = r.point(rec.t); rec.normal = (rec.p - center(r._time)) / radius; rec.mat = material; return(true); } } return(false); }
// 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 override bool scatter(Ray r_in, hit_record rec, ref Vector3 attenuation, ref Ray scattered) { Vector3 reflected = Utils.reflect(r_in.direction().unit_vector(), rec.normal); scattered = new Ray(rec.p, reflected + fuzz * Utils.random_in_unit_sphere()); attenuation = abledo.value(0.0f, 0.0f, ref rec.p); return(Vector3.dot(scattered.direction(), rec.normal) > 0.0f); }
public override bool scatter(Ray r_in, hit_record rec, ref Vector3 attenuation, ref Ray scattered) { Vector3 outward_norm; Vector3 reflected = Utils.reflect(r_in.direction(), rec.normal); float ni_over_nt; attenuation = new Vector3(1.0f, 1.0f, 1.0f); Vector3 refracted = new Vector3(); float reflect_prob = 0.0f; float cosine = 0.0f; if (Vector3.dot(r_in.direction(), rec.normal) > 0.0f) { outward_norm = -1.0f * rec.normal; ni_over_nt = reflect_index; cosine = reflect_index * Vector3.dot(r_in.direction(), rec.normal) / r_in.direction().length(); } else { outward_norm = rec.normal; ni_over_nt = 1.0f / reflect_index; cosine = -1.0f * Vector3.dot(r_in.direction(), rec.normal) / r_in.direction().length(); } // determine probability for reflecting vs refracting based on if a refraction is possible if (Utils.refract(r_in.direction(), outward_norm, ni_over_nt, ref refracted)) { reflect_prob = Utils.schlick(cosine, reflect_index); } else { scattered = new Ray(rec.p, reflected); reflect_prob = 1.0f; } // decide whether to reflect or refract if (Utils.rnd.NextDouble() < reflect_prob) { scattered = new Ray(rec.p, reflected); } else { scattered = new Ray(rec.p, refracted); } return(true); }
public bool hit(Ray r, float tmin, float tmax) { float t0 = Utils.fmin((_min.x() - r.origin().x()) / r.direction().x(), (_max.x() - r.origin().x()) / r.direction().x()); float t1 = Utils.fmax((_min.x() - r.origin().x()) / r.direction().x(), (_max.x() - r.origin().x()) / r.direction().x()); tmin = Utils.fmax(t0, tmin); tmax = Utils.fmin(t1, tmax); if (tmax <= tmin) { return(false); } t0 = Utils.fmin((_min.y() - r.origin().y()) / r.direction().y(), (_max.y() - r.origin().y()) / r.direction().y()); t1 = Utils.fmax((_min.y() - r.origin().y()) / r.direction().y(), (_max.y() - r.origin().y()) / r.direction().y()); tmin = Utils.fmax(t0, tmin); tmax = Utils.fmin(t1, tmax); if (tmax <= tmin) { return(false); } t0 = Utils.fmin((_min.z() - r.origin().z()) / r.direction().z(), (_max.z() - r.origin().z()) / r.direction().z()); t1 = Utils.fmax((_min.y() - r.origin().y()) / r.direction().y(), (_max.z() - r.origin().z()) / r.direction().z()); tmin = Utils.fmax(t0, tmin); tmax = Utils.fmin(t1, tmax); if (tmax <= tmin) { return(false); } return(true); }