コード例 #1
0
        public Color3 Dielectric(Intersection intersection)
        {
            var   n1 = intersection.Ray.Medium.RefractiveIndex;
            var   n2 = intersection.Material.RefractiveIndex;
            float n  = n1 / n2;

            var ray    = intersection.Ray;
            var normal = intersection.SurfaceNormal;

            float cost = Vector3.Dot(normal, -ray.Direction);
            float k    = 1 - n * n * (1 - cost * cost);

            if (k < 0)
            {
                //internal reflection
                return(Specular(intersection));
            }

            var T = n * ray.Direction + normal * (n * cost - (float)Math.Sqrt(k));

            var refracted = Ray.CreateFromIntersection(intersection, T, float.MaxValue, true);

            float R0 = (n1 - n2) / (n1 + n2);

            R0 *= R0;
            var   a  = 1 - cost;
            float Fr = R0 + (1 - R0) * a * a * a * a * a;
            float Ft = 1 - Fr;

            var transparency = new Vector3(1);

            if (intersection.InsidePrimitive)
            {
                var absorbance = intersection.Ray.Medium.Color * intersection.Ray.Medium.Absorbance * -intersection.Distance;
                transparency = new Vector3(
                    (float)Math.Exp(-absorbance.R),
                    (float)Math.Exp(-absorbance.G),
                    (float)Math.Exp(-absorbance.B));
            }

            //go inside
            if (_rng.RandomFloat() < Ft)
            {
                return(transparency * _scene.Sample(refracted, _rng, false));
            }

            //reflect outside
            return(transparency * Specular(intersection));
        }
コード例 #2
0
        private Color3 SampleLightDirectly(ISurfaceLight light, Color3 brdf, Intersection intersection)
        {
            var rPoint = light.GetRandomPoint(_rng, intersection); //get random point on light
            var l      = rPoint.Location - intersection.Location;  //vector to light
            var dist   = l.LengthFast;

            l.Normalize();
            var lightRay   = Ray.CreateFromIntersection(intersection, l, dist); //ray to light
            var nlightDotL = Vector3.Dot(rPoint.Normal, -l);                    //light normal dot light
            var nDotL      = Vector3.Dot(intersection.SurfaceNormal, l);        //normal dot light

            if (nDotL > 0 && nlightDotL > 0 && !IntersectionHelper.DoesIntersect(lightRay, _scene.Objects, light))
            {
                var solidAngle = (nlightDotL * light.Area) / (dist * dist); //light area on hemisphere
                return(light.Color * solidAngle * brdf * nDotL);
            }

            return(Color4.Black);
        }
コード例 #3
0
        public Color3 DirectIllumination(Intersection intersection)
        {
            var totalIntensity = 0.0f;

            foreach (var light in _scene.PointLights)
            {
                var lightVector       = light.Position - intersection.Location;
                var invLightDistance2 = 1 / lightVector.LengthSquared;
                var shadowRay         = Ray.CreateFromIntersection(intersection, lightVector, lightVector.LengthFast);
                if (IntersectionHelper.DoesIntersect(shadowRay, _scene.Objects) && !(intersection.IntersectsWith is DebugSphere)) //todo debug
                {
                    continue;
                }

                var intensity = Vector3.Dot(intersection.SurfaceNormal, shadowRay.Direction);
                totalIntensity += Math.Max(intensity, 0) * invLightDistance2 * light.Intensity;
            }

            return(totalIntensity * intersection.Material.CalculateColor(intersection.Location));
        }
コード例 #4
0
        public Color3 Diffuse(Intersection intersection)
        {
            float killChance = 0;

            if (_russianRoulette)
            {
                killChance = GetKillChance(intersection.Material.Color);
                if (_rng.TestChance(killChance))
                {
                    return(Color4.Black);
                }
            }

            //random reflected ray
            Vector3 rDir;

            if (_cosineDist)
            {
                rDir = _rng.CosineDistributed(intersection.SurfaceNormal);
            }
            else
            {
                rDir = _rng.RandomVectorOnHemisphere(intersection.SurfaceNormal);
            }

            var reflected = Ray.CreateFromIntersection(intersection, rDir, goesIntoMaterial: true);

            //brdf of material
            var brdf = intersection.Material.CalculateColor(intersection) / MathHelper.Pi;

            //irradiance
            var nDotR = Vector3.Dot(intersection.SurfaceNormal, rDir);
            var Ei    = _scene.Sample(reflected, _rng, true) * nDotR;

            Color3 Ld = Color4.Black;

            //use next event estimation?
            if (_nee)
            {
                if (_scene.SurfaceLights.Count > 0)
                {
                    //sample light directly - next event estimation
                    var ranLight = _scene.SurfaceLights.GetRandom(_rng.R); //get random light
                    Ld = SampleLightDirectly(ranLight, brdf, intersection) * _scene.SurfaceLights.Count * ranLight.Brightness;
                }
            }

            Color3 result;

            if (_cosineDist)
            {
                //probability density function
                var pdf = nDotR / MathHelper.Pi;
                result = brdf * Ei / pdf + Ld;
            }
            else
            {
                result = MathHelper.TwoPi * brdf * Ei + Ld;
            }

            return(result / (1 - killChance));
        }