Beispiel #1
0
        public virtual List<ZBufferItem> Trace(Ray ray, Matrix transform, Vector3 translation)
        {
            var intersections = new List<ZBufferItem>();

            foreach (var primitive in Triangles)
            {
                var items = primitive.Trace(ray, transform, translation);
                intersections.AddRange(items);
            }

            return intersections;
        }
Beispiel #2
0
        /// <summary>
        /// Get the colour at this point on this triangle
        /// </summary>
        public Color Colorise(Scene scene, Shapes.Ray ray, Matrix transform, Vector3 translation, Vector3 intersection)
        {
            var colour = new Color();

            foreach (var light in scene.Lights)
            {
                // get the vector between the light and the point
                var lightv = Vector3.Normalize(intersection - light.Position);
                var distance = Vector3.Distance(intersection, light.Position);

                // get the texture colour
                var a = Shader.Ambient(light, distance);

                colour += a;

                var lightraydir = light.Position - intersection;
                lightraydir.Normalize();

                // don't intersect with the object i'm on
                var lightrayorigin = intersection + 0.01f*lightraydir;
                var lightray = new Ray(lightrayorigin, lightraydir);

                var lightx = scene.Trace(lightray, transform, translation);

                if (!lightx.Any())
                {
                    var l = Shader.Lambertian(Normal, light, lightv, distance);
                    var s = Shader.Specular(Normal, ray.Direction, light, lightv, distance);

                    colour += l;
                    colour += s;
                }
            }

            return colour;
        }
Beispiel #3
0
        /// <summary>
        /// Möller–Trumbore ray-triangle intersection algorithm
        /// </summary>
        /// <param name="ray">ray to test</param>
        /// <param name="transform">world rotation transform</param>
        /// <param name="translation">translation vector</param>
        /// <returns>list of intersections</returns>
        public List<ZBufferItem> Trace(Ray ray, Matrix transform, Vector3 translation)
        {
            var buffer = new List<ZBufferItem>();

            var ts = Vertices.Select(vertex => Vector3.TransformCoordinate(vertex, transform)).Select(vertex => vertex + translation).ToArray();

            // find vectors for two edges sharing ts[0]
            var edge1 = ts[1] - ts[0];
            var edge2 = ts[2] - ts[0];

            var cross = Vector3.Cross(ray.Direction, edge2);
            var det = Vector3.Dot(edge1, cross);

            // if det is near 0 then ray is in the plane of the triangle i.e. parallel
            if (det > -float.Epsilon && det < float.Epsilon)
            {
                return buffer;
            }

            var invDet = 1f/det;

            var T = ray.Origin - ts[0];
            var u = Vector3.Dot(T, cross)*invDet;

            // if u is not 0->1 then intersection is outside the triangle
            if (u < 0f || u > 1f)
            {
                return buffer;
            }

            var Q = Vector3.Cross(T, edge1);
            var v = Vector3.Dot(ray.Direction, Q)*invDet;

            // then intersection is outside the triangle
            if (v < 0f || u + v > 1f)
            {
                return new List<ZBufferItem>();
            }

            var t = Vector3.Dot(edge2, Q)*invDet;

            // ray intersection!
            if (t > float.Epsilon)
            {
                // get the point of intersection
                var ix = ray.Origin + t*ray.Direction;
                buffer.Add(new ZBufferItem(this, ix, translation));
            }

            return buffer;
        }
Beispiel #4
0
 public Color Colorise(Scene scene, Ray ray, Matrix transform, Vector3 translation, Vector3 intersection)
 {
     // this is never called
     return Color.BlanchedAlmond;
 }
        private Color TraceRay(Matrix transform, int x, int y, int width, int height)
        {
            var camPositionScaled = Vector3.Divide(_scene.Camera.Position, _scene.Camera.Scale);

            // work out the orientation of the image plane
            var camDir = _scene.Camera.Target - camPositionScaled;
            var xDir = Vector3.Cross(Vector3.UnitY, camDir);
            var yDir = Vector3.Cross(camDir, xDir); // now correct the up dir
            camDir.Normalize();
            xDir.Normalize();
            yDir.Normalize();

            // now get the uv coordinates on our image plane, scaled by unitsize
            const float unitsize = 0.1f;
            var u = (float)((x - 0.5 * width) * unitsize);
            var v = (float)((y - 0.5 * height) * unitsize);

            // now move u units along x, v units along y, starting at camposition
            var uv = camPositionScaled + u * xDir + v * yDir;

            // now the direction of the ray from uv to the target
            var rayDir = _scene.Camera.Target - uv;
            rayDir.Normalize();

            // get the actual ray
            var ray = new Shapes.Ray(uv, rayDir);
            
            var bounces = new List<ZBufferItem>();
            const int iterations = 2;
            for (var i = 0; i < iterations; i++)
            {
                var items = _scene.Trace(ray, transform, _scene.Origin);

                if (items.Any())
                {
                    var closest = items.OrderByDescending(d => d.Distance(ray.Origin)).First();

                    bounces.Add(closest);

                    if (closest.Primitive.Shader.IsReflective)
                    {
                        var reflectedRay = -ray.Direction -
                                           2*Vector3.Dot(-ray.Direction, closest.Primitive.Normal)*
                                           closest.Primitive.Normal;
                        reflectedRay.Normalize();

                        // don't want to intersect the reflection plane
                        var reflectionOrigin = closest.Intersection + 0.01f*reflectedRay;

                        ray = new Shapes.Ray(reflectionOrigin, reflectedRay);

                        //var reflections = _scene.Trace(ray, transform, _scene.Origin);

                        //if (reflections.Any())
                        //{
                        //    bounces.Add(reflections.OrderByDescending(d => d.Distance(ray.Origin)).First());
                        //}
                    }
                }
            }

            if (bounces.Any())
            {
                var c = new Color();
                foreach (var bounce in bounces)
                {
                    var closestColour = bounce.Primitive.Colorise(_scene, ray, transform, bounce.Translation, bounce.Intersection);

                    var avgColour = Color.Scale(closestColour, 1f/bounces.Count);
                    c += avgColour;
                }
                c.A = 255;
                return c;
            }

            return _scene.Ambient();
        }