static void printColor(UnityEngine.Vector3 color)
        {
            color = Exten.clamp01(color);
            int r = (int)(color.x * 255.99f);
            int g = (int)(color.y * 255.99f);
            int b = (int)(color.z * 255.99f);

            print("{0} {1} {2} ", r, g, b);
        }
 UnityEngine.Vector3 random_in_unit_disk()
 {
     UnityEngine.Vector3 p;
     do
     {
         p = 2.0f * new UnityEngine.Vector3(Exten.rand01(), Exten.rand01(), 0) - new UnityEngine.Vector3(1, 1, 0);
     } while (UnityEngine.Vector3.Dot(p, p) >= 1.0f);
     return(p);
 }
        public bool Scatter(Ray ray, UnityEngine.Vector3 point, UnityEngine.Vector3 normal, out UnityEngine.Vector3 attenuation, out Ray scattered)
        {
            var reflected = Exten.reflect(ray.direction, normal);

            if (fuzz > 0)
            {
                reflected = reflected + fuzz * Exten.RandomVecInSphere();
            }
            scattered   = new Ray(point, reflected);
            attenuation = color;
            return(UnityEngine.Vector3.Dot(ray.direction, normal) < 0);
        }
        public static void Main(UnityEngine.Texture2D texture, int sampleCount = 5)
        {
            int width  = texture.width;
            int height = texture.height;

            Exten.r = new Random(0);
            //scene = random_scene();

            UnityEngine.Vector3 lookfrom = new UnityEngine.Vector3(3, 3, 2);
            UnityEngine.Vector3 lookat   = new UnityEngine.Vector3(0, 0, -1);
            float dist_to_focus          = (lookat - lookfrom).length();
            float aperture = 2.0f;


            Camera camera = new Camera(lookfrom, lookat, new UnityEngine.Vector3(0, 1, 0), 60, (float)(width) / (float)(height), aperture, dist_to_focus);

            //print("P3\n{0} {1}\n255\n", width, height);

            for (int i = height - 1; i >= 0; --i)
            {
                for (int j = 0; j < width; ++j)
                {
                    var c = new UnityEngine.Vector3(0, 0, 0);
                    for (int k = 0; k < sampleCount; ++k)
                    {
                        float x = (j + Exten.rand01()) / (float)width;
                        float y = (i + Exten.rand01()) / (float)height;
                        var   r = camera.GenRay(x, y);
                        Profiler.BeginSample("RayingRay");
                        c += RayTracing(r, 0);
                        Profiler.EndSample();
                    }
                    c /= sampleCount;
                    var c1 = c.gamma();
                    UnityEngine.Color outColor = new UnityEngine.Color(c1.x, c1.y, c1.z, 1);
                    texture.SetPixel(j, i, outColor);
                }
            }
        }
        static Hitable random_scene()
        {
            int n = 500;

            Hitable[] list = new Hitable[n + 1];
            list[0] = new Sphere(new UnityEngine.Vector3(0, -1000, 0), 1000, new Metal(new UnityEngine.Vector3(0.5f, 0.5f, 0.5f), 0.1f));
            int i = 1;

            for (int a = -11; a < 11; a++)
            {
                for (int b = -11; b < 11; b++)
                {
                    float choose_mat = Exten.rand01();
                    var   center     = new UnityEngine.Vector3(a + 0.9f * Exten.rand01(), 0.2f, b + 0.9f * Exten.rand01());
                    if ((center - new UnityEngine.Vector3(4f, 0.2f, 0f)).length() > 0.9f)
                    {
                        if (choose_mat < 0.8)
                        {  // diffuse
                            list[i++] = new Sphere(center, 0.2f, new Lambertian(new UnityEngine.Vector3(Exten.rand01() * Exten.rand01(), Exten.rand01() * Exten.rand01(), Exten.rand01() * Exten.rand01())));
                        }
                        else if (choose_mat < 0.95f)
                        { // metal
                            list[i++] = new Sphere(center, 0.2f,
                                                   new Metal(new UnityEngine.Vector3(0.5f * (1 + drand48()), 0.5f * (1 + drand48()), 0.5f * (1 + drand48())), 0.5f * drand48()));
                        }
                        else
                        {  // glass
                            list[i++] = new Sphere(center, 0.2f, new Dieletric(1.5f));
                        }
                    }
                }
            }

            list[i++] = new Sphere(new UnityEngine.Vector3(2, 1, 0), 1.0f, new Dieletric(1.3f));
            //list[i++] = new Sphere(new vec3(-3, 1, 2), 1.0f, new Metal(new vec3(0.4f, 0.2f, 0.1f),0.2f));
            //list[i++] = new Sphere(new vec3(4, 1, 0), 1.0f, new Metal(new vec3(0.7f, 0.6f, 0.5f), 0.0f));
            //list[i++] = new Sphere(new vec3(4, 1, -0.5f), 1.0f, new Metal(new vec3(0.7f, 0.6f, 0.5f), 0.0f));
            return(new HitList(list.Where(p => p != null).ToArray()));
        }
        public bool Scatter(Ray ray, UnityEngine.Vector3 point, UnityEngine.Vector3 normal, out UnityEngine.Vector3 attenuation, out Ray scattered)
        {
            attenuation = new UnityEngine.Vector3(1.0f, 1.0f, 1.0f);
            float eta = ref_idx;
            var   n   = normal;


            if (UnityEngine.Vector3.Dot(ray.direction, normal) > 0)//从内到外
            {
                n = new UnityEngine.Vector3(-normal.x, -normal.y, -normal.z);
            }
            else
            {
                eta = 1.0f / eta;
            }

            UnityEngine.Vector3 r;
            float prob = 1.0f;

            if (Exten.refract(ray.direction, n, eta, out r))
            {
                float cosi = -UnityEngine.Vector3.Dot(ray.direction, n);
                float cost = -UnityEngine.Vector3.Dot(r, n);
                prob = fresnel(cosi, cost, eta);
            }
            if (Exten.rand01() < prob)
            {
                UnityEngine.Vector3 reflected = Exten.reflect(ray.direction, normal);
                scattered = new Ray(point, reflected);
            }
            else
            {
                scattered = new Ray(point, r);
            }
            return(true);
        }
 static float drand48()
 {
     return(Exten.rand01());
 }
 public bool Scatter(Ray ray, UnityEngine.Vector3 point, UnityEngine.Vector3 normal, out UnityEngine.Vector3 attenuation, out Ray scattered)
 {
     scattered   = new Ray(point, normal + Exten.RandomVecInSphere());
     attenuation = color;
     return(true);
 }