Example #1
0
        private Vector3 SampleLight(Shape Shape, Vector3 Hit, Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, Vector3 BSDFAttenuation)
        {
            //If this is not diffuse or there are no lights, no direct lighting calculation needs to be done
            if (SampledLobe != LobeType.DiffuseReflection || World.Lights.Count == 0)
            {
                return(Vector3.Zero);
            }

            //Pick a light
            World.PickLight(out Shape Light, out double LightPickPDF);
            Vector3 Emission = Light.Material.GetProperty("emission", UV).Color;

            Vector3 TotalDirectLighting = Vector3.Zero;

            //Sample BSDF
            if (BSDFAttenuation != Vector3.Zero)
            {
                //Visibility check
                World.Raycast(new Ray(Hit + SampleDirection * 0.001, SampleDirection), out Shape BSDFShape, out Vector3 BSDFHit, out Vector3 BSDFNormal, out Vector2 BSDFUV);
                if (BSDFShape == Light)
                {
                    //Calculate light pdf for bsdf sample
                    double LightPDF = Math.Pow((Hit - BSDFHit).Length(), 2) / (Vector3.Dot(BSDFNormal, Vector3.Normalize(Hit - BSDFHit)) * Light.Area());

                    //Calculate bsdf pdf for bsdf sample
                    Shape.Material.PDF(ViewDirection, Normal, UV, SampleDirection, SampledLobe, out double ScatterPDF);

                    //Weighted sum of the 2 sampling strategies for this sample
                    TotalDirectLighting += BSDFAttenuation * Emission * Util.BalanceHeuristic(ScatterPDF, LightPDF) / ScatterPDF;
                }
            }

            //Sample light directly
            Vector3 LightSample = Light.Sample() - Hit;
            double  Distance    = LightSample.Length();

            LightSample.Normalize();

            //Visibility check
            World.Raycast(new Ray(Hit + LightSample * 0.001, LightSample), out Shape LightShape, out Vector3 LightHit, out Vector3 LightNormal, out Vector2 LightUV);
            if ((LightHit - Hit).Length() >= Distance - 0.001)
            {
                //Calculate light pdf for light sample,
                double LightPDF = Math.Pow(Distance, 2) / (Vector3.Dot(LightNormal, -LightSample) * Light.Area());

                //Calculate bsdf pdf for light sample
                Shape.Material.Evaluate(ViewDirection, Normal, UV, LightSample, SampledLobe, out BSDFAttenuation);
                Shape.Material.PDF(ViewDirection, Normal, UV, LightSample, SampledLobe, out double ScatterPDF);

                //Weighted sum of the 2 sampling strategies for this sample
                if (BSDFAttenuation != Vector3.Zero)
                {
                    TotalDirectLighting += BSDFAttenuation * Emission * Util.BalanceHeuristic(LightPDF, ScatterPDF) / LightPDF;
                }
            }

            return(TotalDirectLighting / LightPickPDF);
        }