Beispiel #1
0
    private Vector3D GetColor(Ray r, HitableList world, Hitable lightShape, int depth)
    {
        HitRecord hRec;

        /*这里的0.001不能改为0,当tmin设0的时候会导致,遍历hitlist时候,ray的t求解出来是0,
         * hit的时候全走了else,导致递归到50层的时候,最后return的是0,* attenuation结果还是0。
         * 距离越远,散射用到random_in_unit_sphere生成的ray误差越大
         */
        if (world.Hit(r, 0.001f, float.MaxValue, out hRec))
        {
            ScatterRecord sRec;
            Vector3D      emitted = hRec.matPtr.Emitted(r, hRec, hRec.u, hRec.v, hRec.p);
            if (depth < 50 && hRec.matPtr.Scatter(r, hRec, out sRec))
            {
                if (sRec.isSpecular)
                {
                    Vector3D c = GetColor(sRec.specularRay, world, lightShape, depth + 1);
                    return(new Vector3D(sRec.attenuation.X * c.X, sRec.attenuation.Y * c.Y, sRec.attenuation.Z * c.Z));
                }
                PDF p;
                if (lightShape != null)
                {
                    HitablePDF p0 = new HitablePDF(lightShape, hRec.p);
                    p = new MixturePDF(p0, sRec.pdfPtr);
                    ((MixturePDF)p).MixRatio = scene.MixRatio;
                }
                else
                {
                    p = sRec.pdfPtr;
                }
                //CosinePDF p = new CosinePDF(hRec.normal);
                Ray      scattered = new Ray(hRec.p, p.Generate(), r.Time);
                float    pdfVal    = p.Value(scattered.Direction);
                Vector3D color     = GetColor(scattered, world, lightShape, depth + 1);  //每次光线衰减之后深度加一
                return(emitted + hRec.matPtr.ScatteringPDF(r, hRec, scattered)
                       * new Vector3D(sRec.attenuation.X * color.X, sRec.attenuation.Y
                                      * color.Y, sRec.attenuation.Z * color.Z) / pdfVal);
            }
            else
            {
                return(emitted);
            }
        }
        else
        {
            if (isSky)
            {
                Vector3D unitDirection = r.Direction.UnitVector();
                float    t             = 0.5f * (unitDirection.Y + 1f);
                return((1 - t) * new Vector3D(1, 1, 1) + t * new Vector3D(0.5f, 0.7f, 1));
            }
            return(new Vector3D(0, 0, 0));
        }
    }
Beispiel #2
0
    private Vector3D GetColor(Ray r, HitableList world, int depth)
    {
        HitRecord rec;

        /*这里的0.001不能改为0,当tmin设0的时候会导致,遍历hitlist时候,ray的t求解出来是0,
         * hit的时候全走了else,导致递归到50层的时候,最后return的是0,* attenuation结果还是0。
         * 距离越远,散射用到random_in_unit_sphere生成的ray误差越大
         */
        if (world.Hit(r, 0.001f, float.MaxValue, out rec))
        {
            Ray      scattered;
            Vector3D emitted = rec.matPtr.Emitted(r, rec, rec.u, rec.v, rec.p);
            Vector3D albedo;
            float    pdfVal;
            if (depth < 50 && rec.matPtr.Scatter(r, rec, out albedo, out scattered, out pdfVal))
            {
                Hitable    lightSphape = new XZRect(213, 343, 227, 332, 554, new Lambertian());
                HitablePDF p0          = new HitablePDF(lightSphape, rec.p);
                CosinePDF  p1          = new CosinePDF(rec.normal);
                MixturePDF p           = new MixturePDF(p0, p1);
                scattered = new Ray(rec.p, p.Generate(), r.Time);
                pdfVal    = p.Value(scattered.Direction);
                Vector3D color = GetColor(scattered, world, depth + 1);       //每次光线衰减之后深度加一
                return(emitted + rec.matPtr.ScatteringPDF(r, rec, scattered)
                       * new Vector3D(albedo.X * color.X, albedo.Y * color.Y, albedo.Z * color.Z) / pdfVal);
            }
            else
            {
                return(emitted);
            }
        }
        else
        {
            //Vector3D unitDirection = r.Direction.UnitVector();
            //float t = 0.5f * (unitDirection.Y + 1f);
            //return (1 - t) * new Vector3D(1, 1, 1) + t * new Vector3D(0.5f, 0.7f, 1);
            return(new Vector3D(0, 0, 0));
        }
    }