Пример #1
0
        public Color PathTrace(Ray ray, HitRecord record, List <List <Sample> > subPathSamples, LightSample lightSample)
        {
            float q          = 0f;
            int   depth      = 0;
            Color pixelColor = new Color(0, 0, 0);
            Color alpha      = new Color(1, 1, 1);

            bool isGeneratedFromRefraction = false;

            while (depth < Constants.MaximalPathLength)
            {
                if (record == null)
                {
                    return(pixelColor);
                }
                //Select one light at random
                ILight light = Randomizer.PickRandomLight(lights);
                //Sample that light
                light.Sample(record, lightSample);

                if (isGeneratedFromRefraction && record.HitObject.Light != null)
                {
                    isGeneratedFromRefraction = false;
                    pixelColor.Append(record.HitObject.Light.LightColor);
                }

                pixelColor.Append(alpha.Mult(Shade(record, lightSample)).Div(lightSample.Pdf));

                //Break with Russian roulette
                if (depth > 2)
                {
                    q = 0.5f;
                    if (random.NextDouble() <= q)
                    {
                        return(pixelColor);
                    }
                }

                List <Sample> directionSamples = subPathSamples[depth];
                //Create the next Ray
                if (record.Material is LambertMaterial || record.Material is BlinnPhongMaterial)
                {
                    Sample  directionSample = Randomizer.PickRandomSample(directionSamples);
                    Vector3 direction       = UniformHemisphereSample(directionSample.X, directionSample.Y, record.SurfaceNormal);
                    record = scene.Intersect(new Ray(record.IntersectionPoint, direction));
                    if (record == null)
                    {
                        break;
                    }
                    alpha = alpha.Mult(record.Material.Diffuse.Div(1 - q));
                }
                else if (record.Material is MirrorMaterial)
                {
                    record = scene.Intersect(record.CreateReflectedRay());
                    isGeneratedFromRefraction = true;
                }
                else if (record.Material is RefractiveMaterial)
                {
                    isGeneratedFromRefraction = true;
                    float fresnel = Reflectance(record);
                    //Pick refraction / reflection path with p=0.5 each
                    if (random.NextDouble() < fresnel)
                    {
                        record = scene.Intersect(record.CreateReflectedRay());
                        alpha  = alpha.Mult(fresnel);
                    }
                    else
                    {
                        record = scene.Intersect(record.CreateRefractedRay());
                        alpha  = alpha.Mult(1 - fresnel);
                    }
                }

                depth++;
            }
            return(pixelColor);
        }