private Vector CalculateRefractionRadiance(Ray ray, int depth, Point x, Vector n, Vector nl, Sphere obj, Color f)
        {
            var reflRay = new Ray(x, ray.Direction - n * 2 * n.Dot(ray.Direction)); // Ideal dielectric REFRACTION
            var into = n.Dot(nl) > 0; // Ray from outside going in?
            const int Nc = 1;
            const double Nt = 1.5;
            var nnt = @into ? Nc / Nt : Nt / Nc;
            var ddn = ray.Direction.Dot(nl);

            double cos2T;
            if((cos2T = 1 - nnt * nnt * (1 - ddn * ddn)) < 0) { // Total internal reflection
                return obj.Emission + f.Multiply(Radiance(reflRay, depth));
            }

            var tdir = (ray.Direction * nnt - n * ((@into ? 1 : -1) * (ddn * nnt + Math.Sqrt(cos2T)))).Normalize();
            const double A = Nt - Nc;
            const double B = Nt + Nc;
            const double R0 = A * A / (B * B);
            var c = 1 - (@into ? -ddn : tdir.Dot(n));
            var re = R0 + (1 - R0) * c * c * c * c * c;
            var tr = 1 - re;
            var pp = .25 + .5 * re;
            var rp = re / pp;
            var tp = tr / (1 - pp);

            return obj.Emission + f.Multiply(depth > 2 ? (random.NextDouble() < pp ? // Russian roulette
                Radiance(reflRay, depth) * rp : Radiance(new Ray(x, tdir), depth) * tp) :
                Radiance(reflRay, depth) * re + Radiance(new Ray(x, tdir), depth) * tr);
        }
Beispiel #2
0
 // --- Public Methods ---
 public Intersection Intersect(Ray ray)
 {
     var op = Position - ray.Origin; // Solve t^2*Direction.Direction + 2*t*(Origin-Position).Direction + (Origin-Position).(Origin-Position)-R^2 = 0
     double t;
     const double Epsilon = 1e-4;
     var b = op.Dot(ray.Direction);
     var det = b * b - op.Dot(op) + radius * radius;
     if(det < 0) {
         return Intersection.Miss;
     }
     det = Math.Sqrt(det);
     return (t = b - det) > Epsilon ? new Intersection(ray, this, t) : ((t = b + det) > Epsilon ? new Intersection(ray, this, t) : Intersection.Miss);
 }
        private Vector Radiance(Ray ray, int depth)
        {
            var intersection = scene.Intersect(ray);
            if(intersection.IsMiss) {
                return Vector.Zero; // if miss, return black
            }

            var sphere = intersection.Sphere; // the hit object
            if(depth > 100) { // *** Added to prevent stack overflow
                return sphere.Emission;
            }

            var x = ray.Origin + ray.Direction * intersection.Distance;
            var n = (x - sphere.Position).Normalize();
            var nl = n.Dot(ray.Direction) < 0 ? n : n * -1;
            var color = sphere.Color;
            var p = color.Red > color.Green && color.Red > color.Blue ? color.Red : color.Green > color.Blue ? color.Green : color.Blue; // max ReflectionType

            if(++depth > 5) {
                if(random.NextDouble() < p) {
                    color = color * (1 / p);
                }
                else {
                    return sphere.Emission; //R.R.
                }
            }

            if(sphere.ReflectionType == ReflectionType.Diffuse) { // Ideal DIFFUSE reflection
                return CalculateDiffuseRadiance(depth, nl, sphere, color, x);
            }

            if(sphere.ReflectionType == ReflectionType.Specular) { // Ideal SPECULAR reflection
                return CalculateSpecularRadiance(ray, depth, sphere, color, x, n);
            }

            return CalculateRefractionRadiance(ray, depth, x, n, nl, sphere, color);
        }
 private Vector CalculateSpecularRadiance(Ray ray, int depth, Sphere obj, Color f, Point x, Vector n)
 {
     return obj.Emission + f.Multiply(Radiance(new Ray(x, ray.Direction - n * 2 * n.Dot(ray.Direction)), depth));
 }