Esempio n. 1
0
 public override void PDF(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out double PDF)
 {
     PDF = 1;
 }
Esempio n. 2
0
 public override void Sample(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, out Vector3 SampleDirection, out LobeType SampledLobe)
 {
     SampleDirection = -ViewDirection;
     SampledLobe     = LobeType.DiffuseTransmission;
 }
Esempio n. 3
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);
        }
Esempio n. 4
0
 public override void Evaluate(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out Vector3 Attenuation)
 {
     Attenuation = GetProperty("albedo", UV);
 }
Esempio n. 5
0
 public override void PDF(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out double PDF)
 {
     PDF = (Vector3.Dot(SampleDirection, Normal) / Math.PI);
 }
Esempio n. 6
0
 public abstract void PDF(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out double PDF);
Esempio n. 7
0
        public override void Sample(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, out Vector3 SampleDirection, out LobeType SampledLobe)
        {
            double RefractiveIndex = GetProperty("ior", UV);
            double Roughness       = GetProperty("roughness", UV);

            //Reflection
            if (Util.Random.NextDouble() <= Util.FresnelReal(MathHelper.Clamp(Vector3.Dot(-ViewDirection, Normal), -1, 1), RefractiveIndex))
            {
                SampledLobe     = LobeType.SpecularReflection;
                SampleDirection = Vector3.Reflect(-ViewDirection, Normal);
            }
            else
            {
                SampledLobe     = LobeType.SpecularTransmission;
                SampleDirection = Vector3.Refract(-ViewDirection, Normal, RefractiveIndex);
            }

            if (Roughness > 0)
            {
                SampleDirection = Util.SampleGGX(Util.Random.NextDouble(), Util.Random.NextDouble(), SampleDirection, Roughness);
            }
        }
Esempio n. 8
0
        public override void Evaluate(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out Vector3 Attenuation)
        {
            Vector3 Albedo    = GetProperty("albedo", UV);
            double  Metalness = GetProperty("metalness", UV);
            Vector3 F0        = Vector3.Lerp(new Vector3(0.04), Albedo, Metalness);

            double DiffuseSpecularRatio = 0.5 + (0.5 * Metalness);

            double  CosTheta = Math.Max(Vector3.Dot(Normal, SampleDirection), 0);
            Vector3 Halfway  = Vector3.Normalize(SampleDirection + ViewDirection);
            Vector3 Ks       = Util.FresnelSchlick(Math.Max(Vector3.Dot(Halfway, ViewDirection), 0.0), F0);

            if (SampledLobe == LobeType.DiffuseReflection)
            {
                Vector3 Kd = Vector3.One - Ks;

                Kd *= 1.0 - Metalness;
                Vector3 Diffuse = Kd * Albedo / Math.PI;

                Attenuation = Diffuse * CosTheta / (1 - DiffuseSpecularRatio);
            }
            else
            {
                double Roughness = GetProperty("roughness", UV);

                double  D = Util.GGXDistribution(Normal, Halfway, Roughness);
                double  G = Util.GeometrySmith(Normal, ViewDirection, SampleDirection, Roughness);
                Vector3 SpecularNumerator   = D * G * Ks;
                double  SpecularDenominator = 4.0 * Math.Max(Vector3.Dot(Normal, ViewDirection), 0.0) * CosTheta + 0.001;
                Vector3 Specular            = SpecularNumerator / SpecularDenominator;

                Attenuation = Specular * CosTheta / DiffuseSpecularRatio;
            }
        }
Esempio n. 9
0
 public override void Evaluate(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out Vector3 Attenuation)
 {
     throw new NotImplementedException();
 }
Esempio n. 10
0
 public override void Evaluate(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out Vector3 Attenuation)
 {
     if (SampledLobe == LobeType.SpecularReflection)
     {
         Attenuation = Vector3.One;
     }
     else
     {
         Attenuation = GetProperty("albedo", UV);
     }
 }
Esempio n. 11
0
 public override void PDF(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out double PDF)
 {
     throw new NotImplementedException();
 }
Esempio n. 12
0
 public override void Sample(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, out Vector3 SampleDirection, out LobeType SampledLobe)
 {
     throw new NotImplementedException();
 }
Esempio n. 13
0
 public abstract void Evaluate(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out Vector3 Attenuation);
Esempio n. 14
0
        public override void Sample(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, out Vector3 SampleDirection, out LobeType SampledLobe)
        {
            double DiffuseSpecularRatio = 0.5 + (0.5 * GetProperty("metalness", UV));

            if (Util.Random.NextDouble() > DiffuseSpecularRatio)
            {
                SampledLobe = LobeType.DiffuseReflection;

                Util.CreateCartesian(Normal, out Vector3 NT, out Vector3 NB);

                double  R1     = Util.Random.NextDouble();
                double  R2     = Util.Random.NextDouble();
                Vector3 Sample = Util.CosineSampleHemisphere(R1, R2);
                SampleDirection = new Vector3(
                    Sample.X * NB.X + Sample.Y * Normal.X + Sample.Z * NT.X,
                    Sample.X * NB.Y + Sample.Y * Normal.Y + Sample.Z * NT.Y,
                    Sample.X * NB.Z + Sample.Y * Normal.Z + Sample.Z * NT.Z);
                SampleDirection.Normalize();
            }

            //Glossy
            else
            {
                SampledLobe = LobeType.SpecularReflection;

                double Roughness = MathHelper.Clamp(GetProperty("roughness", UV), 0.001, 1);

                Vector3 ReflectionDirection = Vector3.Reflect(-ViewDirection, Normal);
                double  R1 = Util.Random.NextDouble();
                double  R2 = Util.Random.NextDouble();
                SampleDirection = Util.SampleGGX(R1, R2, ReflectionDirection, Roughness);
            }
        }
Esempio n. 15
0
        public override void Evaluate(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out Vector3 Attenuation)
        {
            double InverseSigmaSquared = 1.0 / Math.Pow(GetProperty("sigma", UV), 2);
            double NdotV = Vector3.Dot(Normal, ViewDirection);
            double NdotL = Vector3.Dot(Normal, SampleDirection);

            if (NdotV > 0 && NdotL > 0)
            {
                Vector3 Halfway = Vector3.Normalize(SampleDirection + ViewDirection);

                double NdotH = Vector3.Dot(Normal, Halfway);
                double VdotH = Math.Abs(Vector3.Dot(ViewDirection, Halfway));

                if (Math.Abs(NdotH) < 0.99999 && VdotH > 0.00001)
                {
                    double NdotHdivVdotH = NdotH / VdotH;
                    NdotHdivVdotH = Math.Max(NdotHdivVdotH, 0.00001);

                    double FactorView  = 2 * Math.Abs(NdotHdivVdotH * NdotV);
                    double FactorLight = 2 * Math.Abs(NdotHdivVdotH * NdotL);

                    double SinNdotHSquared  = 1 - NdotH * NdotH;
                    double SinNdotHCubed    = SinNdotHSquared * SinNdotHSquared;
                    double CoTangentSquared = (NdotH * NdotH) / SinNdotHSquared;

                    double D = Math.Exp(-CoTangentSquared * InverseSigmaSquared) * InverseSigmaSquared * (1.0 / Math.PI) / SinNdotHCubed;
                    double G = Math.Min(1.0, Math.Min(FactorView, FactorLight));

                    double BSDFEval = 0.25 * (D * G) / NdotV;

                    //BSDF attenuation * Albedo * Uniform hemisphere PDF
                    Attenuation = new Vector3(BSDFEval, BSDFEval, BSDFEval) * GetProperty("albedo", UV).Color;
                }
                else
                {
                    Attenuation = Vector3.Zero;
                }
            }
            else
            {
                Attenuation = Vector3.Zero;
            }
        }
Esempio n. 16
0
 public override void PDF(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out double PDF)
 {
     if (SampledLobe == LobeType.DiffuseReflection)
     {
         PDF = (Vector3.Dot(SampleDirection, Normal) / Math.PI);
     }
     else
     {
         Vector3 Halfway = Vector3.Normalize(SampleDirection + ViewDirection);
         double  D       = Util.GGXDistribution(Normal, Halfway, GetProperty("roughness", UV));
         PDF = (D * Vector3.Dot(Normal, Halfway) / (4 * Vector3.Dot(Halfway, ViewDirection)) + 0.0001);
     }
 }
Esempio n. 17
0
 public override void PDF(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out double PDF)
 {
     PDF = (1.0 / (2.0 * Math.PI));
 }
Esempio n. 18
0
 public override void Evaluate(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, Vector3 SampleDirection, LobeType SampledLobe, out Vector3 Attenuation)
 {
     Attenuation = GetProperty("albedo", UV).Color / Math.PI * Math.Max(Vector3.Dot(Normal, SampleDirection), 0);
 }
Esempio n. 19
0
        private Vector3 Trace(Ray Ray)
        {
            Medium CurrentMedium = null;

            LobeType SampledLobe = LobeType.SpecularReflection;

            Vector3 FinalColor = Vector3.Zero;
            Vector3 Throughput = Vector3.One;

            for (int Bounce = 0; Bounce < MaxBounces; Bounce++)
            {
                //Raycast to nearest geometry, if any
                World.Raycast(Ray, out Shape Shape, out Vector3 Hit, out Vector3 Normal, out Vector2 UV);

                //Return skybox color if nothing hit
                if (Shape == null)
                {
                    if (SkyBox == null)
                    {
                        FinalColor += Throughput * Vector3.One;
                    }
                    else
                    {
                        FinalColor += Throughput * SkyBox.GetColorAtUV(new Vector2(1 - (1.0 + Math.Atan2(Ray.Direction.Z, Ray.Direction.X) / MathHelper.Pi) * 0.5, 1 - Math.Acos(Ray.Direction.Y) / MathHelper.Pi));
                    }
                    break;
                }

                //Volumetrics, slightly borken
                bool Scattered = false;
                if (CurrentMedium != null)
                {
                    double MaxDistance = (Hit - Ray.Origin).Length();

                    double  Distance     = CurrentMedium.SampleDistance(MaxDistance);
                    Vector3 Transmission = CurrentMedium.Transmission(Distance);
                    Throughput *= Transmission;

                    if (Distance < MaxDistance)
                    {
                        Scattered = true;

                        Ray.Direction = CurrentMedium.SampleDirection(Ray.Direction);
                        Ray.Origin    = Hit + Ray.Direction * 0.001;
                    }
                }

                //If no scattering event happened, do normal path tracing
                if (!Scattered)
                {
                    //Area lights
                    if (Shape.Material.HasProperty("emission"))
                    {
                        //Don't add emission to diffuse term if NEE is on, we already sample it directly
                        if (SampledLobe == LobeType.SpecularReflection || !NEE)
                        {
                            FinalColor += Throughput * Shape.Material.GetProperty("emission", UV).Color;
                        }
                        break;
                    }

                    Vector3 ViewDirection = Vector3.Normalize(Ray.Origin - Hit);

                    //Sample BSDF
                    Shape.Material.Sample(ViewDirection, Normal, UV, out Vector3 SampleDirection, out SampledLobe);
                    Shape.Material.PDF(ViewDirection, Normal, UV, SampleDirection, SampledLobe, out double PDF);
                    Shape.Material.Evaluate(ViewDirection, Normal, UV, SampleDirection, SampledLobe, out Vector3 Attenuation);

                    //Sample direct lighting
                    if (NEE)
                    {
                        FinalColor += Throughput * SampleLight(Shape, Hit, ViewDirection, Normal, UV, SampleDirection, SampledLobe, Attenuation);
                    }

                    //Accumulate BSDF attenuation
                    Throughput *= Attenuation / PDF;

                    //If we entered a medium, update current medium
                    if (SampledLobe == LobeType.SpecularTransmission || SampledLobe == LobeType.DiffuseTransmission)
                    {
                        CurrentMedium = Shape.Material.Medium;
                    }

                    //Set new ray direction to sampled ray
                    Ray.Origin    = Hit + SampleDirection * 0.001;
                    Ray.Direction = SampleDirection;
                }

                //Russian roulette
                if (Bounce >= MinBounces)
                {
                    double Prob = Math.Max(Throughput.X, Math.Max(Throughput.Y, Throughput.Z));
                    if (Util.Random.NextDouble() > Prob)
                    {
                        break;
                    }
                    Throughput *= 1.0 / Prob;
                }
            }

            return(FinalColor);
        }
Esempio n. 20
0
        public override void Sample(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, out Vector3 SampleDirection, out LobeType SampledLobe)
        {
            SampledLobe = LobeType.DiffuseReflection;

            Util.CreateCartesian(Normal, out Vector3 NT, out Vector3 NB);
            double  R1     = Util.Random.NextDouble();
            double  R2     = Util.Random.NextDouble();
            Vector3 Sample = Util.CosineSampleHemisphere(R1, R2);

            SampleDirection = new Vector3(
                Sample.X * NB.X + Sample.Y * Normal.X + Sample.Z * NT.X,
                Sample.X * NB.Y + Sample.Y * Normal.Y + Sample.Z * NT.Y,
                Sample.X * NB.Z + Sample.Y * Normal.Z + Sample.Z * NT.Z);
            SampleDirection.Normalize();
        }
Esempio n. 21
0
 public abstract void Sample(Vector3 ViewDirection, Vector3 Normal, Vector2 UV, out Vector3 SampleDirection, out LobeType SampledLobe);