Пример #1
0
        // вычисление локальной модели освещения
        public Point3D shade(Point3D hit_point, Point3D normal, Point3D color_obj, float diffuse_coef)
        {
            Point3D dir = point_light - hit_point;

            dir = Point3D.norm(dir);                // направление луча из источника света в точку удара

            Point3D diff = diffuse_coef * color_light * Math.Max(Point3D.scalar(normal, dir), 0);

            return(new Point3D(diff.x * color_obj.x, diff.y * color_obj.y, diff.z * color_obj.z));
        }
Пример #2
0
        // преломление
        public Ray refract(Point3D hit_point, Point3D normal, float eta)
        {
            Ray   res_ray = new Ray();
            float sclr    = Point3D.scalar(normal, direction);

            float k = 1 - eta * eta * (1 - sclr * sclr);

            if (k >= 0)
            {
                float cos_theta = (float)Math.Sqrt(k);
                res_ray.start     = new Point3D(hit_point);
                res_ray.direction = Point3D.norm(eta * direction - (cos_theta + eta * sclr) * normal);
                return(res_ray);
            }
            else
            {
                return(null);
            }
        }
Пример #3
0
        public bool ray_intersects_triangle(Ray r, Point3D p0, Point3D p1, Point3D p2, out float intersect)
        {
            intersect = -1;

            Point3D edge1 = p1 - p0;
            Point3D edge2 = p2 - p0;
            Point3D h     = r.direction * edge2;
            float   a     = Point3D.scalar(edge1, h);

            if (a > -EPS && a < EPS)
            {
                return(false);       // This ray is parallel to this triangle.
            }
            float   f = 1.0f / a;
            Point3D s = r.start - p0;
            float   u = f * Point3D.scalar(s, h);

            if (u < 0 || u > 1)
            {
                return(false);
            }

            Point3D q = s * edge1;
            float   v = f * Point3D.scalar(r.direction, q);

            if (v < 0 || u + v > 1)
            {
                return(false);
            }
            // At this stage we can compute t to find out where the intersection point is on the line.
            float t = f * Point3D.scalar(edge2, q);

            if (t > EPS)
            {
                intersect = t;
                return(true);
            }
            else      // This means that there is a line intersection but not a ray intersection.
            {
                return(false);
            }
        }
Пример #4
0
        public static bool ray_sphere_intersection(Ray r, Point3D sphere_pos, float sphere_rad, out float t)
        {
            Point3D k = r.start - sphere_pos;
            float   b = Point3D.scalar(k, r.direction);
            float   c = Point3D.scalar(k, k) - sphere_rad * sphere_rad;
            float   d = b * b - c;

            t = 0;

            if (d >= 0)
            {
                float sqrtd = (float)Math.Sqrt(d);
                float t1    = -b + sqrtd;
                float t2    = -b - sqrtd;

                float min_t = Math.Min(t1, t2);
                float max_t = Math.Max(t1, t2);

                t = (min_t > EPS) ? min_t : max_t;
                return(t > EPS);
            }
            return(false);
        }
Пример #5
0
        // отражение
        public Ray reflect(Point3D hit_point, Point3D normal)
        {
            Point3D reflect_dir = direction - 2 * normal * Point3D.scalar(direction, normal);

            return(new Ray(hit_point, hit_point + reflect_dir));
        }
Пример #6
0
        public Point3D RayTrace(Ray r, int iter, float env)
        {
            if (iter <= 0)
            {
                return(new Point3D(0, 0, 0));
            }

            float    t                     = 0; // позиция точки пересечения луча с фигурой на луче
            Point3D  normal                = null;
            Material m                     = new Material();
            Point3D  res_color             = new Point3D(0, 0, 0);
            bool     refract_out_of_figure = false; //  луч преломления выходит из объекта?

            foreach (Figure fig in scene)
            {
                if (fig.figure_intersection(r, out float intersect, out Point3D n))
                {
                    if (intersect < t || t == 0)     // нужна ближайшая фигура к точке наблюдения
                    {
                        t      = intersect;
                        normal = n;
                        m      = new Material(fig.figure_material);
                    }
                }
            }

            if (t == 0)
            {
                return(new Point3D(0, 0, 0));
            }
            //если угол между нормалью к поверхности объекта и направлением луча положительный, => угол острый, => луч выходит из объекта в среду
            if (Point3D.scalar(r.direction, normal) > 0)
            {
                normal *= -1;
                refract_out_of_figure = true;
            }

            Point3D hit_point = r.start + r.direction * t;

            foreach (Light l in lights)
            {
                Point3D amb = l.color_light * m.ambient;
                amb.x      = (amb.x * m.clr.x);
                amb.y      = (amb.y * m.clr.y);
                amb.z      = (amb.z * m.clr.z);
                res_color += amb;

                // диффузное освещение
                if (is_visible(l.point_light, hit_point))
                {
                    res_color += l.shade(hit_point, normal, m.clr, m.diffuse);
                }
            }

            if (m.reflection > 0)
            {
                Ray reflected_ray = r.reflect(hit_point, normal);
                res_color += m.reflection * RayTrace(reflected_ray, iter - 1, env);
            }

            if (m.refraction > 0)
            {
                float eta;                 //коэффициент преломления
                if (refract_out_of_figure) //луч выходит в среду
                {
                    eta = m.environment;
                }
                else
                {
                    eta = 1 / m.environment;
                }

                Ray refracted_ray = r.refract(hit_point, normal, eta);
                if (refracted_ray != null)
                {
                    res_color += m.refraction * RayTrace(refracted_ray, iter - 1, m.environment);
                }
            }

            return(res_color);
        }