private void CreateToyPathTracerScene()
        {
            // This is the scene used in the "ToyPathTracer" project by Aras Pranckevičius
            // https://github.com/aras-p/ToyPathTracer

            Vector3 lookfrom    = new Vector3(0, 2, 3);
            Vector3 lookat      = new Vector3(0, 0, 0);
            float   distToFocus = 3;
            float   aperture    = 0.1f;

            aperture *= 0.2f;

            _sceneParams.Camera = Camera.Create(
                lookfrom,
                lookat,
                Vector3.UnitY,
                60,
                (float)Width / Height,
                aperture,
                distToFocus);

            _spheres = new[]
            {
                Sphere.Create(new Vector3(0, -100.5f, -1), 100),
                Sphere.Create(new Vector3(2, 0, -1), 0.5f),
                Sphere.Create(new Vector3(0, 0, -1), 0.5f),
                Sphere.Create(new Vector3(-2, 0, -1), 0.5f),
                Sphere.Create(new Vector3(2, 0, 1), 0.5f),
                Sphere.Create(new Vector3(0, 0, 1), 0.5f),
                Sphere.Create(new Vector3(-2, 0, 1), 0.5f),
                Sphere.Create(new Vector3(0.5f, 1, 0.5f), 0.5f),
                Sphere.Create(new Vector3(-1.5f, 1.5f, 0f), 0.3f),
                Sphere.Create(new Vector3(4, 0, -3), 0.5f), Sphere.Create(new Vector3(3, 0, -3), 0.5f), Sphere.Create(new Vector3(2, 0, -3), 0.5f), Sphere.Create(new Vector3(1, 0, -3), 0.5f), Sphere.Create(new Vector3(0, 0, -3), 0.5f), Sphere.Create(new Vector3(-1, 0, -3), 0.5f), Sphere.Create(new Vector3(-2, 0, -3), 0.5f), Sphere.Create(new Vector3(-3, 0, -3), 0.5f), Sphere.Create(new Vector3(-4, 0, -3), 0.5f),
                Sphere.Create(new Vector3(4, 0, -4), 0.5f), Sphere.Create(new Vector3(3, 0, -4), 0.5f), Sphere.Create(new Vector3(2, 0, -4), 0.5f), Sphere.Create(new Vector3(1, 0, -4), 0.5f), Sphere.Create(new Vector3(0, 0, -4), 0.5f), Sphere.Create(new Vector3(-1, 0, -4), 0.5f), Sphere.Create(new Vector3(-2, 0, -4), 0.5f), Sphere.Create(new Vector3(-3, 0, -4), 0.5f), Sphere.Create(new Vector3(-4, 0, -4), 0.5f),
                Sphere.Create(new Vector3(4, 0, -5), 0.5f), Sphere.Create(new Vector3(3, 0, -5), 0.5f), Sphere.Create(new Vector3(2, 0, -5), 0.5f), Sphere.Create(new Vector3(1, 0, -5), 0.5f), Sphere.Create(new Vector3(0, 0, -5), 0.5f), Sphere.Create(new Vector3(-1, 0, -5), 0.5f), Sphere.Create(new Vector3(-2, 0, -5), 0.5f), Sphere.Create(new Vector3(-3, 0, -5), 0.5f), Sphere.Create(new Vector3(-4, 0, -5), 0.5f),
                Sphere.Create(new Vector3(4, 0, -6), 0.5f), Sphere.Create(new Vector3(3, 0, -6), 0.5f), Sphere.Create(new Vector3(2, 0, -6), 0.5f), Sphere.Create(new Vector3(1, 0, -6), 0.5f), Sphere.Create(new Vector3(0, 0, -6), 0.5f), Sphere.Create(new Vector3(-1, 0, -6), 0.5f), Sphere.Create(new Vector3(-2, 0, -6), 0.5f), Sphere.Create(new Vector3(-3, 0, -6), 0.5f), Sphere.Create(new Vector3(-4, 0, -6), 0.5f),
                Sphere.Create(new Vector3(1.5f, 1.5f, -2), 0.3f),
            };

            _materials = new[]
            {
                Material.Lambertian(new Vector3(0.8f, 0.8f, 0.8f)),
                Material.Lambertian(new Vector3(0.8f, 0.4f, 0.4f)),
                Material.Lambertian(new Vector3(0.4f, 0.8f, 0.4f)),
                Material.Metal(new Vector3(0.4f, 0.4f, 0.8f), 0),
                Material.Metal(new Vector3(0.4f, 0.8f, 0.4f), 0),
                Material.Metal(new Vector3(0.4f, 0.8f, 0.4f), 0.2f),
                Material.Metal(new Vector3(0.4f, 0.8f, 0.4f), 0.6f),
                Material.Dielectric(1.5f),
                Material.Lambertian(new Vector3(0.8f, 0.6f, 0.2f)),
                Material.Lambertian(new Vector3(0.1f, 0.1f, 0.1f)), Material.Lambertian(new Vector3(0.2f, 0.2f, 0.2f)), Material.Lambertian(new Vector3(0.3f, 0.3f, 0.3f)), Material.Lambertian(new Vector3(0.4f, 0.4f, 0.4f)), Material.Lambertian(new Vector3(0.5f, 0.5f, 0.5f)), Material.Lambertian(new Vector3(0.6f, 0.6f, 0.6f)), Material.Lambertian(new Vector3(0.7f, 0.7f, 0.7f)), Material.Lambertian(new Vector3(0.8f, 0.8f, 0.8f)), Material.Lambertian(new Vector3(0.9f, 0.9f, 0.9f)),
                Material.Metal(new Vector3(0.1f, 0.1f, 0.1f), 0f), Material.Metal(new Vector3(0.2f, 0.2f, 0.2f), 0f), Material.Metal(new Vector3(0.3f, 0.3f, 0.3f), 0f), Material.Metal(new Vector3(0.4f, 0.4f, 0.4f), 0f), Material.Metal(new Vector3(0.5f, 0.5f, 0.5f), 0f), Material.Metal(new Vector3(0.6f, 0.6f, 0.6f), 0f), Material.Metal(new Vector3(0.7f, 0.7f, 0.7f), 0f), Material.Metal(new Vector3(0.8f, 0.8f, 0.8f), 0f), Material.Metal(new Vector3(0.9f, 0.9f, 0.9f), 0f),
                Material.Metal(new Vector3(0.8f, 0.1f, 0.1f), 0f), Material.Metal(new Vector3(0.8f, 0.5f, 0.1f), 0f), Material.Metal(new Vector3(0.8f, 0.8f, 0.1f), 0f), Material.Metal(new Vector3(0.4f, 0.8f, 0.1f), 0f), Material.Metal(new Vector3(0.1f, 0.8f, 0.1f), 0f), Material.Metal(new Vector3(0.1f, 0.8f, 0.5f), 0f), Material.Metal(new Vector3(0.1f, 0.8f, 0.8f), 0f), Material.Metal(new Vector3(0.1f, 0.1f, 0.8f), 0f), Material.Metal(new Vector3(0.5f, 0.1f, 0.8f), 0f),
                Material.Lambertian(new Vector3(0.8f, 0.1f, 0.1f)), Material.Lambertian(new Vector3(0.8f, 0.5f, 0.1f)), Material.Lambertian(new Vector3(0.8f, 0.8f, 0.1f)), Material.Lambertian(new Vector3(0.4f, 0.8f, 0.1f)), Material.Lambertian(new Vector3(0.1f, 0.8f, 0.1f)), Material.Lambertian(new Vector3(0.1f, 0.8f, 0.5f)), Material.Lambertian(new Vector3(0.1f, 0.8f, 0.8f)), Material.Lambertian(new Vector3(0.1f, 0.1f, 0.8f)), Material.Metal(new Vector3(0.5f, 0.1f, 0.8f), 0f),
                Material.Lambertian(new Vector3(0.1f, 0.2f, 0.5f))
            };
        }
        private void CreateBookScene(ref uint state)
        {
            Vector3 camPos      = new Vector3(9.5f, 2f, 2.5f);
            Vector3 lookAt      = new Vector3(3, 0.5f, 0.65f);
            float   distToFocus = (camPos - lookAt).Length();
            float   aperture    = 0.01f;

            _sceneParams.Camera = Camera.Create(
                camPos,
                lookAt,
                Vector3.UnitY,
                25f,
                (float)Width / Height,
                aperture,
                distToFocus);

            List <Sphere>   spheres   = new List <Sphere>();
            List <Material> materials = new List <Material>();

            spheres.Add(Sphere.Create(new Vector3(0, -1000, 0), 1000));
            materials.Add(Material.Lambertian(new Vector3(0.5f, 0.5f, 0.5f)));

            int dimension = 5;

            for (int a = -dimension; a < dimension; a++)
            {
                for (int b = -dimension; b < dimension; b++)
                {
                    float   chooseMaterial = RandUtil.RandomFloat(ref state);
                    Vector3 center         = new Vector3(a + 0.9f * RandUtil.RandomFloat(ref state), 0.15f, b + 0.9f * RandUtil.RandomFloat(ref state));
                    if ((center - new Vector3(4, 0.2f, 0)).Length() > 0.9f)
                    {
                        float randOffset = RandUtil.RandomFloat(ref state) * 0.15f;
                        spheres.Add(Sphere.Create(center + Vector3.UnitY * randOffset, 0.15f + randOffset));
                        if (chooseMaterial < 0.8f)
                        {
                            materials.Add(Material.Lambertian(
                                              new Vector3(
                                                  RandUtil.RandomFloat(ref state) * RandUtil.RandomFloat(ref state),
                                                  RandUtil.RandomFloat(ref state) * RandUtil.RandomFloat(ref state),
                                                  RandUtil.RandomFloat(ref state) * RandUtil.RandomFloat(ref state))));
                        }
                        else if (chooseMaterial < 0.95f)
                        {
                            materials.Add(Material.Metal(
                                              new Vector3(
                                                  0.5f * (1 + RandUtil.RandomFloat(ref state)),
                                                  0.5f * (1 + RandUtil.RandomFloat(ref state)),
                                                  0.5f * (1 + RandUtil.RandomFloat(ref state))),
                                              0.5f * (1 + RandUtil.RandomFloat(ref state))));
                        }
                        else
                        {
                            materials.Add(Material.Dielectric(1.5f));
                        }
                    }

                    Debug.Assert(spheres.Count == materials.Count);
                }
            }

            spheres.Add(Sphere.Create(new Vector3(0, 1, 0), 1));
            materials.Add(Material.Dielectric(1.5f));

            spheres.Add(Sphere.Create(new Vector3(-4, 1, 0), 1));
            materials.Add(Material.Lambertian(new Vector3(0.4f, 0.2f, 0.1f)));

            spheres.Add(Sphere.Create(new Vector3(4, 1, 0), 1));
            materials.Add(Material.Metal(new Vector3(0.7f, 0.6f, 0.5f), 0f));

            _spheres   = spheres.ToArray();
            _materials = materials.ToArray();
        }