コード例 #1
0
        private double ComputeLighting(Vector point, Vector normal, Vector view, int specular)
        {
            var    i = 0.0;
            Vector L = new Vector();

            foreach (var light in _scene.Lights)
            {
                if (light.Type == LightType.Ambient)
                {
                    i += light.Intensity;
                }
                else
                {
                    double tMax = 0;
                    if (light.Type == LightType.Point)
                    {
                        L    = light.Position.Subtract(point);
                        tMax = 1;
                    }

                    if (light.Type == LightType.Direct)
                    {
                        L    = light.Direction.Multiply(-1);
                        tMax = double.PositiveInfinity;
                    }

                    var(shadowPrimitive, _) = ClosestIntersection(point, L, 0.001, tMax);
                    if (shadowPrimitive != null && !shadowPrimitive.LightTransparent)
                    {
                        continue;
                    }

                    var nDotL = normal.DotProduct(L);

                    if (nDotL > 0)
                    {
                        var intensity = light.Intensity * nDotL / (normal.Lenght() * L.Lenght());
                        i += intensity;
                    }

                    if (specular == -1)
                    {
                        continue;
                    }

                    var R     = ReflectRay(L, normal);
                    var rDotV = R.DotProduct(view);
                    if (rDotV > 0)
                    {
                        var tmp = light.Intensity * Math.Pow(rDotV / (R.Lenght() * view.Lenght()), specular);
                        i += tmp;
                    }
                }
            }

            return(i);
        }
コード例 #2
0
        private (double, double) IntersectRaySphere(Vector O, Vector D, Sphere sphere)
        {
            var C  = sphere.Center;
            var r  = sphere.Radius;
            var oc = O.Subtract(C);

            var k1    = D.DotProduct(D);
            var k2    = 2 * oc.DotProduct(D);
            var k3    = oc.DotProduct(oc) - r * r;
            var discr = k2 * k2 - 4 * k1 * k3;

            if (discr < 0)
            {
                return(double.PositiveInfinity, double.PositiveInfinity);
            }

            var t1 = (-k2 + Math.Sqrt(discr)) / (2 * k1);
            var t2 = (-k2 - Math.Sqrt(discr)) / (2 * k1);

            return(t1, t2);
        }
コード例 #3
0
        private Vector TraceRay(Vector O, Vector D, double tMin, double tMax, int depth)
        {
            var(closestPrimitive, closest_t) = ClosestIntersection(O, D, tMin, tMax);
            if (closestPrimitive == null)
            {
                return(Vector.FromColor(_options.BgColor));
            }

            var view = D.Multiply(-1);
            var P    = O.Add(D.Multiply(closest_t));

            Vector normal = new Vector();

            if (closestPrimitive is Plane plane)
            {
                normal = plane.Normal;
            }

            if (closestPrimitive is Sphere sphere)
            {
                if (sphere.LightTransparent)
                {
                    return(Vector.FromColor(sphere.Color));
                }
                normal = P.Subtract(sphere.Center);
            }

            if (closestPrimitive is Box box)
            {
                normal = box.GetNormal(O, D, tMin);
            }
            if (closestPrimitive is Surface surface)
            {
                normal = surface.GetNormal(O, D, closest_t);
            }
            if (closestPrimitive is Torus torus)
            {
                normal = torus.GetNormal(O, D, closest_t);
            }

            if (closestPrimitive is Disk disk)
            {
                normal = disk.GetNormal();
            }

            normal = normal.Multiply(1 / normal.Lenght()); //unit vector
            if (normal.DotProduct(D) > 0)
            {
                normal = normal.Multiply(-1);
            }

            var color = closestPrimitive.Color;

            if (closestPrimitive is Plane)
            {
                var x = (int)Math.Round(O.D1 + D.D1 * closest_t) % 2;
                var z = (int)Math.Round(O.D3 + D.D3 * closest_t) % 2;
                if (x == z)
                {
                    color = Color.FromRgb(0, 0, 0);
                }
            }

            var local_color = Vector.FromColor(color)
                              .Multiply(ComputeLighting(P, normal, view, closestPrimitive.Specular));

            var r = closestPrimitive.Reflect;

            if (depth <= 0 || r <= 0)
            {
                return(local_color);
            }

            var R = ReflectRay(view, normal);
            var reflectedColor = TraceRay(P, R, 0.001d, double.PositiveInfinity, depth - 1);

            return(local_color.Multiply(1 - r).Add(reflectedColor.Multiply(r)));
        }
コード例 #4
0
 private Vector ReflectRay(Vector r, Vector normal)
 {
     return(normal.Multiply(2 * r.DotProduct(normal)).Subtract(r));
 }