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); }