Пример #1
0
        public override Spectrum f(Vector3 <float> wo, Vector3 <float> wi)
        {
            var cosThetaO = AbsCosTheta(wo);
            var cosThetaI = AbsCosTheta(wi);

            var wh = wi + wo;

            // Handle degenerate cases at grazing angles
            if (cosThetaI == 0 || cosThetaO == 0)
            {
                return(Spectrum.Zero);
            }
            if (wh.LengthSquared() == 0)
            {
                return(Spectrum.Zero);
            }

            wh = wh.Normalized();

            var f = fresnel.Evaluate(wi.Dot(wh));

            // Torrance-Sparrow model
            return
                ((reflectance * distribution.D(wh) * distribution.G(wo, wi) * f) /
                 (4 * cosThetaI * cosThetaO));
        }
Пример #2
0
        public override Spectrum Sample_f(Vector3 <float> wo, out Vector3 <float> wi, Point2 <float> sample, out float pdf, out BxDFType type)
        {
            // Compute the perfect specular reflection direction
            //
            // In polar coordinates:
            //   phi_o = phi_i + pi
            //   theta_o = theta_i
            wi = new Vector3 <float>(-wo.X, -wo.Y, wo.Z); // Simplified because we are in the BRDF coordinate frame

            pdf    = 1;
            sample = null;
            type   = 0; // TODO?
            return(fresnel.Evaluate(CosTheta(wi)) * reflectance * (1.0f / AbsCosTheta(wi)));
        }
Пример #3
0
        public override SampledSpectrum F(Vector3 incoming, Vector3 leaving)
        {
            var cosThetaO = AbsCosTheta(ref leaving);
            var cosThetaI = AbsCosTheta(ref incoming);

            if (cosThetaI == 0 || cosThetaO == 0)
            {
                return(new SampledSpectrum(0));
            }
            var wh        = Vector3.Add(incoming, leaving).Normalized();
            var cosThetaH = Vector3.Dot(incoming, leaving);
            var f         = _fresnel.Evaluate(cosThetaH);

            return(_spectrum * _distribution.D(ref wh) * G(ref incoming, ref leaving, ref wh) * f / (4 * cosThetaI * cosThetaO));
        }
Пример #4
0
        public RgbColor Evaluate(Vector3 outDir, Vector3 inDir, bool isOnLightSubpath)
        {
            if (!ShadingSpace.SameHemisphere(outDir, inDir))
            {
                return(RgbColor.Black);
            }

            float   cosThetaO  = ShadingSpace.AbsCosTheta(outDir);
            float   cosThetaI  = ShadingSpace.AbsCosTheta(inDir);
            Vector3 halfVector = inDir + outDir;

            // Handle degenerate cases for microfacet reflection
            if (cosThetaI == 0 || cosThetaO == 0)
            {
                return(RgbColor.Black);
            }
            if (halfVector.X == 0 && halfVector.Y == 0 && halfVector.Z == 0)
            {
                return(RgbColor.Black);
            }

            // For the Fresnel call, make sure that wh is in the same hemisphere
            // as the surface normal, so that total internal reflection is handled correctly.
            halfVector = Vector3.Normalize(halfVector);
            if (ShadingSpace.CosTheta(halfVector) < 0)
            {
                halfVector = -halfVector;
            }

            var cosine = Vector3.Dot(inDir, halfVector);
            var f      = fresnel.Evaluate(cosine);

            var nd = distribution.NormalDistribution(halfVector);
            var ms = distribution.MaskingShadowing(outDir, inDir);

            return(tint * nd * ms * f / (4 * cosThetaI * cosThetaO));
        }