public override bool scatter(Ray r_in, Hit_Record rec, ref Vec3 attenuation, ref Ray scattered)
        {
            Vec3 reflected = Vec3.reflect(Vec3.unit_vector(r_in.direction()), rec.normal);

            scattered   = new Ray(rec.p, reflected + fuzz * Vec3.random_in_unit_sphere());
            attenuation = albedo;
            return(Vec3.dot(scattered.direction(), rec.normal) > 0.0f);
        }
        public override bool hit(Ray r, float t_min, float t_max, ref Hit_Record rec)
        {
            Vec3  oc           = r.origin() - center;
            float a            = r.direction().x() * r.direction().x() + r.direction().z() * r.direction().z();
            float b            = 2.0f * (oc.x() * r.direction().x() + oc.z() * r.direction().z());
            float c            = oc.x() * oc.x() + oc.z() * oc.z() - radius * radius;
            float discriminant = b * b - 4 * a * c;

            if (discriminant > 0.0f)
            {
                float 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_at_parameter(rec.t);
                    rec.normal    = (rec.p - center) / radius;
                    rec.normal[1] = 0.0f;
                    rec.mat_type  = mat_type;
                    Helper.get_sphere_uv(rec.p, ref rec.u, ref rec.v);
                    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_at_parameter(rec.t);
                    rec.normal    = (rec.p - center) / radius;
                    rec.normal[1] = 0.0f;
                    rec.mat_type  = mat_type;
                    Helper.get_sphere_uv(rec.p, ref rec.u, ref rec.v);
                    return(true);
                }
            }

            return(false);
        }
        public override bool hit(Ray r, float t_min, float t_max, ref Hit_Record rec)
        {
            // Perform a simplified Pythagorean in 3D to determine if
            // the ray vector intersects with the sphere.
            Vec3  oc           = r.origin() - center;
            float a            = Vec3.dot(r.direction());
            float b            = Vec3.dot(oc, r.direction());
            float c            = Vec3.dot(oc) - radius * radius;
            float discriminant = b * b - a * c;

            if (discriminant > 0.0f)
            {
                float temp = (-b - (float)Math.Sqrt(b * b - a * c)) / a;
                if (temp < t_max && temp > t_min)
                {
                    rec.t        = temp;
                    rec.p        = r.point_at_parameter(rec.t);
                    rec.normal   = (rec.p - center) / radius;
                    rec.mat_type = mat_type;
                    Helper.get_sphere_uv(rec.p, ref rec.u, ref rec.v);
                    return(true);
                }
                temp = (-b + (float)Math.Sqrt(b * b - a * c)) / a;
                if (temp < t_max && temp > t_min)
                {
                    rec.t        = temp;
                    rec.p        = r.point_at_parameter(rec.t);
                    rec.normal   = (rec.p - center) / radius;
                    rec.mat_type = mat_type;
                    Helper.get_sphere_uv(rec.p, ref rec.u, ref rec.v);
                    return(true);
                }
            }

            return(false);
        }
        public override bool scatter(Ray r_in, Hit_Record rec, ref Vec3 attenuation, ref Ray scattered)
        {
            Vec3  outward_normal;
            Vec3  reflected = Vec3.reflect(r_in.direction(), rec.normal);
            float ni_over_nt;

            attenuation = color;
            Vec3  refracted = new Vec3(1.0f, 0.0f, 0.0f);
            float reflect_prob;
            float cosine;

            if (Vec3.dot(r_in.direction(), rec.normal) > 0.0f)
            {
                outward_normal = -rec.normal;
                ni_over_nt     = ref_idx;
                cosine         = ref_idx * Vec3.dot(r_in.direction(), rec.normal) / r_in.direction().length();
            }
            else
            {
                outward_normal = rec.normal;
                ni_over_nt     = 1.0f / ref_idx;
                cosine         = -Vec3.dot(r_in.direction(), rec.normal) / r_in.direction().length();
            }

            if (refract(r_in.direction(), outward_normal, ni_over_nt, ref refracted))
            {
                reflect_prob = schlick(cosine, ref_idx);
            }
            else
            {
                scattered    = new Ray(rec.p, reflected);
                reflect_prob = 1.0f;
            }

            if (Rng.f() < reflect_prob)
            {
                scattered = new Ray(rec.p, reflected); // reFLEcted
            }
            else
            {
                scattered = new Ray(rec.p, refracted); // reFRActed
            }


            return(true);
        }
Example #5
0
        public static Vec3 color(Ray r, int depth)
        {
            Hit_Record rec;

            rec.t        = 0.0f;
            rec.u        = rec.v = 0.0f;
            rec.p        = null;
            rec.normal   = null;
            rec.mat_type = null;
            if (world.hit(r, 0.001f, float.MaxValue, ref rec))
            {
                Ray  scattered   = new Ray();
                Vec3 attenuation = new Vec3();
                Vec3 emitted     = rec.mat_type.emitted(rec.u, rec.v, rec.p);
                if (depth < ConfigParams.max_bounces && rec.mat_type.scatter(r, rec, ref attenuation, ref scattered))
                {
                    // recursive call, finding color of each object hit
                    return(emitted + attenuation * color(scattered, depth + 1));
                }
                else
                {
                    // too many bounces, or did not scatter (it absorbed the photon)
                    //return new Vec3(0.0f, 0.0f, 0.0f); // return black
                    return(emitted);
                }
            }
            else
            {
                // we hit nothing, so now hit the outer sky

                if (sky_active_flag)
                {
                    Vec3 unit_direction = Vec3.unit_vector(r.direction());

                    // Return a linear interpolation of the sky, based on Y (vertical)
                    // Higher is more white, lower is more blue-gray.
                    float t = 0.5f * (unit_direction.y() + 1.0f);
                    return((1.0f - t) * new Vec3(1.0f, 1.0f, 1.0f) + t * new Vec3(0.5f, 0.7f, 1.0f));
                }

                return(new Vec3(0.0f, 0.0f, 0.0f)); // black sky
            }
        }