Пример #1
0
        // This is where the magic happens! Trace a ray...
        Vector3 Trace(Ray ray, short depth, bool drawDebugLine, bool absorb = false)
        {
            if (depth == maxDepth)
            {
                return(new Vector3());
            }

            // see if the ray hits anything.
            Intersection intersect = scene.Intersect(ray);

            if (intersect == null)
            { // We didn't hit anything. return the background.
                return(GetSkyColor(ray));
            }

            // Draw some debug output.
            if (drawDebugLine)
            {
                Debugger.DrawDebugLine(ray.origin.X, ray.origin.Z,
                                       intersect.intersectionPoint.X,
                                       intersect.intersectionPoint.Z, Color.Green);
            }

            // Magic!
            if (absorb && intersect.GetMaterial().absorbtion.Length() > 0)
            {
                return(intersect.dist
                       * -intersect.GetMaterial().absorbtion
                       + DoFancyColorCalculations(ray, intersect, depth, drawDebugLine));
            }
            else
            {
                return(DoFancyColorCalculations(ray, intersect, depth, drawDebugLine));
            }
        }
Пример #2
0
        public Color trace(Ray ray, int depth)
        {
            if (depth < 1)
            {
                return(new Color(Scene.Background.R, Scene.Background.G, Scene.Background.B));
            }
            Intersection?possibleIntersection = Scene.Intersect(ray);

            if (!possibleIntersection.HasValue)
            {
                return(new Color(Scene.Background.R, Scene.Background.G, Scene.Background.B));
            }
            Intersection intersection = possibleIntersection.Value;

            intersection.Tracer = this;
            if (depth == 4)
            {
            }
            Color result = intersection.Material.Ambient * Scene.Ambient;

            foreach (var light in Scene.Lights)
            {
                Vector lightDir   = light.GetDirAt(intersection.Point);
                double lightPower = light.PowerAt(intersection.Point);
                Color  lightColor = light.shade(intersection);

                Color current = new Color();
                current += ShadingModels.LambertModel(intersection, lightDir) * intersection.Material.Lambert;
                current += ShadingModels.PhongModel(intersection, lightDir) * intersection.Material.Phong;
                current += ShadingModels.BlinnPhongModel(intersection, lightDir) * intersection.Material.BlinnPhong;

                current *= (lightColor * lightPower);

                result += current;
            }

            if (intersection.Material.Reflectance > 0)
            {
                result += intersection.Material.ReflectiveColor * intersection.Material.Reflectance *
                          trace(new Ray(
                                    intersection.Point,
                                    Vector.Reflect(
                                        intersection.Ray.Direction,
                                        intersection.Normal)
                                    ), depth - 1);
            }

            if (intersection.Material.Refractivity > 0)
            {
                Vector?direction = Vector.Refract(
                    intersection.Ray.Direction,
                    intersection.Normal,
                    intersection.Material.RefractivePower
                    );
                if (direction.HasValue)
                {
                    result += intersection.Material.RefractiveColor * intersection.Material.Refractivity *
                              trace(new Ray(intersection.Point, direction.Value), depth - 1);
                }
            }

            return(result);
        }
Пример #3
0
        /// <summary>
        /// The core of the ray tracer.
        /// </summary>
        /// <param name="ray">The direction in which we look</param>
        /// <param name="recursionDepth">How far we can still go in recursion</param>
        /// <returns>The color associated with the ray</returns>
        private Vector3 CalculateColor(Ray ray, int recursionDepth = MAX_RECURSION)
        {
            if (recursionDepth-- <= 0)
            {
                return(Vector3.Zero);                       // recursion depth is reached
            }
            // Check for an intersection:
            Intersection intersection = scene.Intersect(ray);

            if (ray.debug)
            {
                // Debug
                if (recursionDepth == MAX_RECURSION - 1)
                {
                    DrawRayDebug(ray, intersection, 0xff0000); // primary ray
                }
                else
                {
                    DrawRayDebug(ray, intersection, 0x00ff00); // secondary, or higher ray
                }
            }

            Vector3 dir = ray.direction;

            if (intersection == null)
            {
                // The ray doesn't collide with any primitive, so return the color of the skybox
                int texx = Utils.scaleFloat((float)Math.Atan2(dir.Z, dir.X) / MathHelper.TwoPi + 0.5f, skybox.Height);
                int texy = (int)(Utils.SafeAcos(dir.Y) / Math.PI * (skybox.Height - 1));
                return(skybox.Data[texx, texy]);
            }

            // Determine the diffuse and specular parts:
            Material mat = intersection.primitive.material;
            Vector3  ret = Vector3.Zero;

            if (mat.isSpecular)
            {
                // Calculate the reflection vector, and go one level deeper in the recursion
                Vector3 N = intersection.normal;
                // secondary ray, obtained by reflecting the current ray
                Ray ray2 = new Ray(intersection.location, dir - 2 * Vector3.Dot(dir, N) * N);

                // Pass on the same debug values:
                ray2.debug        = ray.debug;
                ray2.debugSurface = ray.debugSurface;
                ray2.camerapos    = ray.camerapos;
                ray2.debugxunit   = ray.debugxunit;
                ray2.debugyunit   = ray.debugyunit;

                // color at the intersection when looking in the reflection direction:
                Vector3 reflected = CalculateColor(ray2, recursionDepth);
                // multiply with the color of this material (in most cases this should be white for a realistic mirror)
                ret += mat.specularity * intersection.primitive.GetDiffuseColor(intersection) * reflected;
            }

            // Diffuse part:
            if (mat.isDiffuse)
            {
                foreach (Light light in scene.lights)
                {
                    // The color is the sum of all the contributions
                    Vector3 intensity = light.GetIntensity(ray, intersection, scene);
                    ret += (1f - mat.specularity) * intensity;
                }
            }
            return(ret);
        }