private Vector3 albedo;//漫反射系数

        public override bool Scatter(Ray rIn, HitRecord rec, ref Vector3 attenuation, ref Ray scattered)
        {
            Vector3 target = rec.P + rec.Normal + RTUtils.RandomInUnitSphere();

            scattered   = new Ray(new Point3D(rec.P.X, rec.P.Y, rec.P.Z), target - rec.P);
            attenuation = albedo;
            return(true);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            int nx = 1080;
            int ny = 1080;
            int ns = 10;

            bmp = new Bitmap(nx, ny);

            Random rd = new Random();

            List <Hitable> list = new List <Hitable>();

            list.Add(new Sphere(new Point3D(0, 0, -1), 0.5, new Lambertian(new Vector3(0.8, 0.3, 0.3))));
            list.Add(new Sphere(new Point3D(0, -100.5, -1), 100, new Lambertian(new Vector3(0.8, 0.8, 0.0))));
            list.Add(new Sphere(new Point3D(1, 0, -1), 0.5, new Metal(new Vector3(0.8, 0.6, 0.2), 0.3)));
            list.Add(new Sphere(new Point3D(-1, 0, -1), 0.5, new Dielectrics(1.5)));
            HitableList world = new HitableList(list, 4);
            Camera      cam   = new Camera(new Point3D(-2, 2, 1), new Point3D(0, 0, -1), new Vector3(0, 1, 0), 90, (double)(nx) / (double)(ny));

            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    Color3D col = new Color3D();
                    for (int s = 0; s < ns; s++)
                    {
                        double  u       = (double)(i + rd.NextDouble()) / (double)nx;
                        double  v       = (double)(j + rd.NextDouble()) / (double)ny;
                        Ray     r       = cam.GetRay(u, v);
                        Color3D colTemp = RTUtils.Color(r, world, 0);
                        col.R += colTemp.R;
                        col.G += colTemp.G;
                        col.B += colTemp.B;
                    }
                    col.R /= ns;
                    col.G /= ns;
                    col.B /= ns;

                    col = new Color3D(Math.Sqrt(col.R), Math.Sqrt(col.G), Math.Sqrt(col.B));

                    int ir = (int)(255.99 * col.R);
                    int ig = (int)(255.99 * col.G);
                    int ib = (int)(255.99 * col.B);
                    bmp.SetPixel(i, ny - j - 1, Color.FromArgb(ir, ig, ib));
                }
            }
            pictureBox1.BackgroundImage = bmp;
        }
        public override bool Scatter(Ray rIn, HitRecord rec, ref Vector3 attenuation, ref Ray scattered)
        {
            Vector3 outwardNormal = new Vector3();
            Vector3 reflected     = RTUtils.Reflect(rIn.Direction, rec.Normal);
            double  niOverNt;

            attenuation = new Vector3(1, 1, 1); //衰减率
            Vector3 refracted = new Vector3();
            double  reflect_prob;
            double  cosine;

            if (Vector3.DotProduct(rIn.Direction, rec.Normal) > 0)
            {
                outwardNormal = rec.Normal * -1;
                niOverNt      = refIdx;
                cosine        = refIdx * Vector3.DotProduct(rIn.Direction, rec.Normal) / rIn.Direction.Length();
            }
            else
            {
                outwardNormal = rec.Normal;
                niOverNt      = 1.0 / refIdx;
                cosine        = -Vector3.DotProduct(rIn.Direction, rec.Normal) / rIn.Direction.Length();
            }

            if (RTUtils.Refract(rIn.Direction, outwardNormal, niOverNt, ref refracted))
            {
                reflect_prob = RTUtils.Schlick(cosine, refIdx);
            }
            else
            {
                scattered    = new Ray(new Point3D(rec.P.X, rec.P.Y, rec.P.Z), reflected);
                reflect_prob = 1.0;
            }
            if (RTUtils.rd.NextDouble() < reflect_prob)
            {
                scattered = new Ray(new Point3D(rec.P.X, rec.P.Y, rec.P.Z), reflected);
            }
            else
            {
                scattered = new Ray(new Point3D(rec.P.X, rec.P.Y, rec.P.Z), refracted);
            }
            return(true);
        }