Пример #1
0
 private static void RenderFunc(int y, int w, int h, int nb_samples,
                                Vector3 eye, Vector3 gaze,
                                Vector3 cx, Vector3 cy,
                                Vector3[] Ls, RNG rng)
 {
     // pixel row
     for (int x = 0; x < w; ++x)
     {
         // pixel column
         for (int sy = 0, i = (h - 1 - y) * w + x; sy < 2; ++sy)
         {
             // 2 subpixel row
             for (int sx = 0; sx < 2; ++sx)
             {
                 // 2 subpixel column
                 Vector3 L = new Vector3();
                 for (int s = 0; s < nb_samples; ++s)
                 {
                     // samples per subpixel
                     double  u1 = 2.0 * rng.UniformFloat();
                     double  u2 = 2.0 * rng.UniformFloat();
                     double  dx = u1 < 1 ? Math.Sqrt(u1) - 1.0 : 1.0 - Math.Sqrt(2.0 - u1);
                     double  dy = u2 < 1 ? Math.Sqrt(u2) - 1.0 : 1.0 - Math.Sqrt(2.0 - u2);
                     Vector3 d  = cx * (((sx + 0.5 + dx) / 2 + x) / w - 0.5) +
                                  cy * (((sy + 0.5 + dy) / 2 + y) / h - 0.5) + gaze;
                     L += Radiance(new Ray(eye + d * 130, d.Normalize(), Sphere.EPSILON_SPHERE), rng) * (1.0 / nb_samples);
                 }
                 Ls[i] += 0.25 * Vector3.Clamp(L);
             }
         }
     }
 }
Пример #2
0
        public static Vector3 Radiance(Ray ray, RNG rng)
        {
            Ray     r = ray;
            Vector3 L = new Vector3();
            Vector3 F = new Vector3(1.0);

            while (true)
            {
                if (!Intersect(r, out int 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: {
                    Vector3 d = Specular.IdealSpecularTransmit(r.d, n, REFRACTIVE_INDEX_OUT, REFRACTIVE_INDEX_IN, out double 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.x) > 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.x * u + sample_d.y * v + sample_d.z * w).Normalize();
                    r = new Ray(p, d, Sphere.EPSILON_SPHERE, double.PositiveInfinity, r.depth + 1);
                    break;
                }
                }
            }
        }
Пример #3
0
        static void Main(string[] args)
        {
            RNG rng        = new RNG();
            int nb_samples = (args.Length > 0) ? int.Parse(args[0]) / 4 : 1;

            const int w = 1024;
            const int h = 768;

            Vector3      eye  = new Vector3(50, 52, 295.6);
            Vector3      gaze = new Vector3(0, -0.042612, -1).Normalize();
            const double fov  = 0.5135;
            Vector3      cx   = new Vector3(w * fov / h, 0.0, 0.0);
            Vector3      cy   = (cx.Cross(gaze)).Normalize() * fov;

            Vector3[] Ls = new Vector3[w * h];
            for (int i = 0; i < w * h; ++i)
            {
                Ls[i] = new Vector3();
            }

            for (int y = 0; y < h; ++y)
            {
                // pixel row
                Console.Write("\rRendering ({0} spp) {1:0.00}%", nb_samples * 4, 100.0 * y / (h - 1));
                for (int x = 0; x < w; ++x)
                {
                    // pixel column
                    for (int sy = 0, i = (h - 1 - y) * w + x; sy < 2; ++sy)
                    {
                        // 2 subpixel row
                        for (int sx = 0; sx < 2; ++sx)
                        {
                            // 2 subpixel column
                            Vector3 L = new Vector3();
                            for (int s = 0; s < nb_samples; ++s)
                            {
                                // samples per subpixel
                                double  u1 = 2.0 * rng.UniformFloat();
                                double  u2 = 2.0 * rng.UniformFloat();
                                double  dx = u1 < 1 ? Math.Sqrt(u1) - 1.0 : 1.0 - Math.Sqrt(2.0 - u1);
                                double  dy = u2 < 1 ? Math.Sqrt(u2) - 1.0 : 1.0 - Math.Sqrt(2.0 - u2);
                                Vector3 d  = cx * (((sx + 0.5 + dx) / 2 + x) / w - 0.5) +
                                             cy * (((sy + 0.5 + dy) / 2 + y) / h - 0.5) + gaze;
                                L += Radiance(new Ray(eye + d * 130, d.Normalize(), Sphere.EPSILON_SPHERE), rng) * (1.0 / nb_samples);
                            }
                            Ls[i] += 0.25 * Vector3.Clamp(L);
                        }
                    }
                }
            }

            ImageIO.WritePPM(w, h, Ls);
        }
Пример #4
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);
            }
        }