Exemple #1
0
        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);
        }
Exemple #2
0
        // 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));
            }
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }