예제 #1
0
        public override SampledSpectrum Sample(Vector3 leaving, out Vector3 incoming)
        {
            var   entering = CosTheta(ref leaving) > 0;
            float ei, et;

            if (entering)
            {
                ei = IndexOfRefractionIncident;
                et = IndexOfRefractionTransmitted;
            }
            else
            {
                et = IndexOfRefractionIncident;
                ei = IndexOfRefractionTransmitted;
            }
            var sinIncidentSquared = SinThetaSquared(ref leaving);
            var eta = ei / et;
            var sinTransmittedSquared = eta * eta * sinIncidentSquared;
            var cosTransmitted        = (float)Math.Sqrt(1 - sinTransmittedSquared);

            if (entering)
            {
                cosTransmitted = -cosTransmitted;
            }
            var sinTOversinI = eta;

            incoming = new Vector3(sinTOversinI * -leaving.X, sinTOversinI * -leaving.Y, cosTransmitted);
            if (sinTransmittedSquared >= 1)
            {
                return(SampledSpectrum.Black());
            }
            var f = _fresnel.Evaluate(CosTheta(ref leaving));

            return((new SampledSpectrum(1) - f) * _s / AbsCosTheta(ref incoming) * (et * et) / (ei * ei));
        }
예제 #2
0
        public RgbColor Evaluate(Vector3 outDir, Vector3 inDir, bool isOnLightSubpath)
        {
            if (ShadingSpace.SameHemisphere(outDir, inDir))
            {
                return(RgbColor.Black);                                             // transmission only
            }
            float cosThetaO = ShadingSpace.CosTheta(outDir);
            float cosThetaI = ShadingSpace.CosTheta(inDir);

            if (cosThetaI == 0 || cosThetaO == 0)
            {
                return(RgbColor.Black);
            }

            // Compute the half vector
            float   eta = ShadingSpace.CosTheta(outDir) > 0 ? (insideIOR / outsideIOR) : (outsideIOR / insideIOR);
            Vector3 wh  = Vector3.Normalize(outDir + inDir * eta);

            if (ShadingSpace.CosTheta(wh) < 0)
            {
                wh = -wh;
            }
            if (Vector3.Dot(outDir, wh) * Vector3.Dot(inDir, wh) > 0)
            {
                return(RgbColor.Black);
            }

            var F = new RgbColor(FresnelDielectric.Evaluate(Vector3.Dot(outDir, wh), outsideIOR, insideIOR));

            float sqrtDenom = Vector3.Dot(outDir, wh) + eta * Vector3.Dot(inDir, wh);
            float factor    = isOnLightSubpath ? (1 / eta) : 1;

            var numerator = distribution.NormalDistribution(wh) * distribution.MaskingShadowing(outDir, inDir);

            numerator *= eta * eta * Math.Abs(Vector3.Dot(inDir, wh)) * Math.Abs(Vector3.Dot(outDir, wh));
            numerator *= factor * factor;

            var denom = (cosThetaI * cosThetaO * sqrtDenom * sqrtDenom);

            Debug.Assert(float.IsFinite(denom));
            return((RgbColor.White - F) * transmittance * Math.Abs(numerator / denom));
        }