Пример #1
0
        private Color Reflection(Ray ray, HitRecord record, int noOfBounce, Color color, IIntersectable objects, List <ILight> lights, ISampler sampler, List <List <Sample> > subPathSamples, LightSample lightSample)
        {
            Color ks = record.Material.Specular;

            if (noOfBounce == Constants.MaximumRecursionDepth)
            {
                return(shadowIntegrator.Integrate(ray, objects, lights, sampler, subPathSamples, lightSample).Mult(ks));
            }

            Ray       reflectedRay  = record.CreateReflectedRay();
            HitRecord reflectRecord = objects.Intersect(reflectedRay);

            if (reflectRecord.HitObject != null)
            {
                if (reflectRecord.Material is MirrorMaterial)
                {
                    Color c = Reflection(reflectedRay, reflectRecord, ++noOfBounce, color, objects, lights, sampler, subPathSamples, lightSample);
                    c.Append(shadowIntegrator.Integrate(reflectedRay, objects, lights, sampler, subPathSamples, lightSample).Mult(ks));
                    return(c);
                }
                else
                {
                    return(shadowIntegrator.Integrate(reflectedRay, objects, lights, sampler, subPathSamples, lightSample).Mult(ks));
                }
            }
            else
            {
                if (SkyBox.IsSkyBoxLoaded())
                {
                    color = SkyBox.GetSkyBoxColor(ray);
                }
            }
            return(color);
        }
Пример #2
0
        private Ray CreateRefractedRay(HitRecord record)
        {
            Vector3 incident = new Vector3(record.CreateReflectedRay().Direction);
            Vector3 normal = new Vector3(record.SurfaceNormal);
            float   n1, n2;
            float   cosI = Vector3.Dot(normal, incident);

            if (cosI < 0)
            {
                //Material to Air
                n1     = record.Material.RefractionIndex;
                n2     = Refractions.AIR;
                normal = -normal;
                cosI   = Vector3.Dot(normal, incident);
            }
            else
            {
                //Air to Material
                n1 = Refractions.AIR;
                n2 = record.Material.RefractionIndex;
            }

            float n = n1 / n2;

            float sinT2 = (float)(n * n * (1.0 - cosI * cosI));

            if (sinT2 > 1.0)
            {
                return(new Ray(record.IntersectionPoint, record.CreateReflectedRay().Direction));             //TIR
            }
            float cosT = (float)Math.Sqrt(1.0 - sinT2);

            Vector3 dir = record.RayDirection;

            dir.Normalize();
            dir    = dir * n;
            normal = normal * (float)(n * cosI - cosT);
            dir   += normal;

            Vector3 pos    = record.IntersectionPoint;
            Vector3 offset = dir;

            offset *= 0.0001f;
            pos    += offset;

            return(new Ray(pos, dir));
        }
Пример #3
0
        private float RSchlick2(HitRecord record)
        {
            Vector3 incident = new Vector3(record.CreateReflectedRay().Direction);
            Vector3 normal = new Vector3(record.SurfaceNormal);
            float   n1, n2;

            float cosX = Vector3.Dot(normal, incident);

            if (cosX < 0)
            {
                //Material to Air
                n1     = record.Material.RefractionIndex;
                n2     = Refractions.AIR;
                normal = -normal;
                cosX   = Vector3.Dot(normal, incident);
            }
            else
            {
                //Air to Material
                n1 = Refractions.AIR;
                n2 = record.Material.RefractionIndex;
            }
            double r0 = (n1 - n2) / (n1 + n2);

            r0 *= r0;
            if (n1 > n2)
            {
                double n     = n1 / n2;
                double sinT2 = n * n * (1.0 - cosX * cosX);
                if (sinT2 > 1.0)
                {
                    return(1.0f);
                }

                cosX = (float)Math.Sqrt(1.0 - sinT2);
            }
            double x = 1.0 - cosX;

            return((float)(r0 + (1.0 - r0) * x * x * x * x * x));
        }
Пример #4
0
        private float Reflectance(HitRecord record)
        {
            Vector3 incident = new Vector3(record.CreateReflectedRay().Direction);
            Vector3 normal   = new Vector3(record.SurfaceNormal);

            float n1, n2;
            float cosI = Vector3.Dot(normal, incident);

            if (cosI < 0)
            {
                //Material to Air
                n1     = record.Material.RefractionIndex;
                n2     = Refractions.AIR;
                normal = -normal;
                cosI   = Vector3.Dot(normal, incident);
            }
            else
            {
                //Air to Material
                n1 = Refractions.AIR;
                n2 = record.Material.RefractionIndex;
            }

            double n     = n1 / n2;
            double sinT2 = n * n * (1.0 - cosI * cosI);

            if (sinT2 > 1.0)
            {
                return(1.0f);             //Total internal Reflection
            }
            double cosT  = Math.Sqrt(1.0 - sinT2);
            double rOrth = (n1 * cosI - n2 * cosT) / (n1 * cosI + n2 * cosT);
            double rPar  = (n2 * cosI - n1 * cosT) / (n2 * cosI + n1 * cosT);

            return((float)(rOrth * rOrth + rPar * rPar) / 2.0f);
        }
Пример #5
0
        private Color GetShadeColor(HitRecord record, int currentDepth)
        {
            if (record != null && record.Distance > 0 && record.Distance < float.MaxValue)
            {
                if (record.Material is MirrorMaterial && currentDepth <= Constants.MaximumRecursionDepth) //Shade Mirror Objects
                {
                    HitRecord mirrorRecord = objects.Intersect(record.CreateReflectedRay());
                    return(GetShadeColor(mirrorRecord, ++currentDepth).Mult(record.Material.Ks));
                }
                if (record.Material is RefractiveMaterial && currentDepth <= Constants.MaximumRecursionDepth) //Shade Reflective Objects
                {
                    float     r              = Reflectance(record);
                    HitRecord reflectionHit  = objects.Intersect(record.CreateReflectedRay());
                    Color     reflectedColor = GetShadeColor(reflectionHit, ++currentDepth).Mult(record.Material.Ks);
                    HitRecord refractedHit   = objects.Intersect(CreateRefractedRay(record));
                    Color     refractedColor = GetShadeColor(refractedHit, ++currentDepth).Mult(record.Material.Ks);
                    Color     retColor       = reflectedColor.Mult(r);
                    retColor.Append(refractedColor.Mult(1 - r));
                    return(retColor);
                }

                if (record.HitObject.Light != null && Constants.IsLightSamplingOn)
                {
                    return(record.HitObject.Light.LightColor);
                }

                Color returnColor = new Color(0, 0, 0);
                foreach (ILight light in lights)
                {
                    Color lightColor = new Color(0, 0, 0);

                    if (Constants.IsLightSamplingOn && Constants.NumberOfLightSamples > 0)
                    {
                        List <LightSample> lightSamples = sampler.GetLightSamples();
                        for (int i = 0; i < Constants.NumberOfLightSamples; i++)
                        {
                            LightSample sample = lightSamples[(int)(random.NextDouble() * lightSamples.Count)];
                            lightSamples.Remove(sample);
                            light.Sample(record, sample);
                            if (IsVisible(record, sample) && sample.LightColor.Power > 0)
                            {
                                if (!(light is AreaLight))
                                {
                                    lightColor.Append(record.Material.Shade(record, sample.Wi).Mult(sample.LightColor));
                                }
                                else
                                {
                                    lightColor.Append(record.Material.Shade(record, sample.Wi).Mult(sample.LightColor).Div(sample.Pdf));
                                }
                            }
                        }
                        returnColor.Append(lightColor.Div(Constants.NumberOfLightSamples));
                    }

                    if (!(light is AreaLight) && IsVisible(record, light))
                    {
                        returnColor.Append(record.HitObject.Material.Shade(record, light.GetLightDirection(record.IntersectionPoint)).Mult(light.GetIncidentColor(record.IntersectionPoint)));
                    }
                }
                return(returnColor);
            }
            return(new Color(0, 0, 0));
        }
Пример #6
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);
        }