예제 #1
0
        public static Vector3 Radiance(Ray ray, RNG rng)
        {
            Ray     r = ray;
            Vector3 L = new Vector3();
            Vector3 F = new Vector3(1.0);

            while (true)
            {
                int id;
                if (!Intersect(r, out id))
                {
                    return(L);
                }

                Sphere  shape = spheres[id];
                Vector3 p     = r.Eval(r.tmax);
                Vector3 n     = (p - shape.p).Normalize();

                L += F * shape.e;
                F *= shape.f;

                // Russian roulette
                if (r.depth > 4)
                {
                    double continue_probability = shape.f.Max();
                    if (rng.UniformFloat() >= continue_probability)
                    {
                        return(L);
                    }
                    F /= continue_probability;
                }

                // Next path segment
                switch (shape.reflection_t)
                {
                case Sphere.Reflection_t.SPECULAR: {
                    Vector3 d = Specular.IdealSpecularReflect(r.d, n);
                    r = new Ray(p, d, Sphere.EPSILON_SPHERE, double.PositiveInfinity, r.depth + 1);
                    break;
                }

                case Sphere.Reflection_t.REFRACTIVE: {
                    double  pr;
                    Vector3 d = Specular.IdealSpecularTransmit(r.d, n, REFRACTIVE_INDEX_OUT, REFRACTIVE_INDEX_IN, out pr, rng);
                    F *= pr;
                    r  = new Ray(p, d, Sphere.EPSILON_SPHERE, double.PositiveInfinity, r.depth + 1);
                    break;
                }

                default: {
                    Vector3 w = n.Dot(r.d) < 0 ? n : -n;
                    Vector3 u = ((Math.Abs(w[0]) > 0.1 ? new Vector3(0.0, 1.0, 0.0) : new Vector3(1.0, 0.0, 0.0)).Cross(w)).Normalize();
                    Vector3 v = w.Cross(u);

                    Vector3 sample_d = Sampling.CosineWeightedSampleOnHemisphere(rng.UniformFloat(), rng.UniformFloat());
                    Vector3 d        = (sample_d[0] * u + sample_d[1] * v + sample_d[2] * w).Normalize();
                    r = new Ray(p, d, Sphere.EPSILON_SPHERE, double.PositiveInfinity, r.depth + 1);
                    break;
                }
                }
            }
        }
예제 #2
0
        public static Vector3 IdealSpecularTransmit(Vector3 d, Vector3 n, double n_out, double n_in, out double pr, RNG rng)
        {
            Vector3 d_Re = IdealSpecularReflect(d, n);

            bool    out_to_in = n.Dot(d) < 0;
            Vector3 nl        = out_to_in ? n : -n;
            double  nn        = out_to_in ? n_out / n_in : n_in / n_out;
            double  cos_theta = d.Dot(nl);
            double  cos2_phi  = 1.0 - nn * nn * (1.0 - cos_theta * cos_theta);

            // Total Internal Reflection
            if (cos2_phi < 0)
            {
                pr = 1.0;
                return(d_Re);
            }

            Vector3 d_Tr = (nn * d - nl * (nn * cos_theta + Math.Sqrt(cos2_phi))).Normalize();
            double  c    = 1.0 - (out_to_in ? -cos_theta : d_Tr.Dot(n));

            double Re   = SchlickReflectance(n_out, n_in, c);
            double p_Re = 0.25 + 0.5 * Re;

            if (rng.UniformFloat() < p_Re)
            {
                pr = (Re / p_Re);
                return(d_Re);
            }
            else
            {
                double Tr   = 1.0 - Re;
                double p_Tr = 1.0 - p_Re;
                pr = (Tr / p_Tr);
                return(d_Tr);
            }
        }