示例#1
0
        public Spectrum SpecularTransmit(
            RayDifferential ray,
            SurfaceInteraction isect,
            Scene scene,
            Sampler sampler,
            int depth)
        {
            Vector3D wo = isect.Wo;
            double   pdf;
            Point3D  p    = isect.P;
            Normal3D ns   = isect.ShadingN;
            Bsdf     bsdf = isect.Bsdf;
            Spectrum f    = bsdf.Sample_f(wo, out Vector3D wi, sampler.Get2D(), out pdf,
                                          out BxdfType sampledType, BxdfType.Transmission | BxdfType.Specular);
            Spectrum L = Spectrum.Create(0.0);

            if (pdf > 0.0 && !f.IsBlack() && wi.AbsDot(ns) != 0.0)
            {
                // Compute ray differential _rd_ for specular transmission
                RayDifferential rd = new RayDifferential(isect.SpawnRay(wi));
                if (ray.HasDifferentials)
                {
                    rd.HasDifferentials = true;
                    rd.RxOrigin         = p + isect.Dpdx.ToPoint3D();
                    rd.RyOrigin         = p + isect.Dpdy.ToPoint3D();

                    double   eta = bsdf.Eta;
                    Vector3D w   = -wo;
                    if (wo.Dot(ns) < 0.0)
                    {
                        eta = 1.0 / eta;
                    }

                    Normal3D dndx = isect.ShadingDndu * isect.Dudx +
                                    isect.ShadingDndv * isect.Dvdx;
                    Normal3D dndy = isect.ShadingDndu * isect.Dudy +
                                    isect.ShadingDndv * isect.Dvdy;

                    Vector3D dwodx = -ray.RxDirection - wo,
                             dwody = -ray.RyDirection - wo;
                    double dDNdx   = dwodx.Dot(ns) + wo.Dot(dndx);
                    double dDNdy   = dwody.Dot(ns) + wo.Dot(dndy);

                    double mu    = eta * w.Dot(ns) - wi.Dot(ns);
                    double dmudx =
                        (eta - (eta * eta * w.Dot(ns)) / wi.Dot(ns)) * dDNdx;
                    double dmudy =
                        (eta - (eta * eta * w.Dot(ns)) / wi.Dot(ns)) * dDNdy;

                    rd.RxDirection =
                        wi + eta * dwodx - (mu * dndx + dmudx * ns).ToVector3D();
                    rd.RyDirection =
                        wi + eta * dwody - (mu * dndy + dmudy * ns).ToVector3D();
                }
                L = f * Li(rd, scene, sampler, depth + 1) * wi.AbsDot(ns) / pdf;
            }
            return(L);
        }
示例#2
0
        /// <inheritdoc />
        public override Spectrum Li(RayDifferential ray, Scene scene, Sampler sampler, int depth = 0)
        {
            Spectrum L = Spectrum.Create(0.0);

            // Find closest ray intersection or return background radiance
            if (!scene.Intersect(ray, out SurfaceInteraction isect))
            {
                foreach (var light in scene.Lights)
                {
                    L += light.Le(ray);
                }
                return(L);
            }

            // Compute emitted and reflected light at ray intersection point

            // Initialize common variables for Whitted integrator
            Normal3D n  = isect.ShadingN;
            Vector3D wo = isect.Wo;

            // Compute scattering functions for surface interaction
            isect.ComputeScatteringFunctions(ray);
            if (isect.Bsdf == null)
            {
                return(Li(new RayDifferential(isect.SpawnRay(ray.Direction)), scene, sampler, depth));
            }

            // Compute emitted light if ray hit an area light source
            L += isect.Le(wo);

            // Add contribution of each light source
            foreach (var light in scene.Lights)
            {
                Spectrum Li =
                    light.Sample_Li(isect, sampler.Get2D(), out Vector3D wi, out double pdf, out VisibilityTester visibility);
                if (Li.IsBlack() || pdf == 0.0)
                {
                    continue;
                }

                Spectrum f = isect.Bsdf.f(wo, wi);
                if (!f.IsBlack() && visibility.Unoccluded(scene))
                {
                    L += f * Li * wi.AbsDot(n) / pdf;
                }
            }
            if (depth + 1 < _maxDepth)
            {
                // Trace rays for specular reflection and refraction
                L += SpecularReflect(ray, isect, scene, sampler, depth);
                L += SpecularTransmit(ray, isect, scene, sampler, depth);
            }
            return(L);
        }
示例#3
0
        public Spectrum SpecularReflect(
            RayDifferential ray,
            SurfaceInteraction isect,
            Scene scene,
            Sampler sampler,
            int depth)
        {
            // Compute specular reflection direction _wi_ and BSDF value
            Vector3D wo   = isect.Wo;
            BxdfType type = BxdfType.Reflection | BxdfType.Specular;
            Spectrum f    = isect.Bsdf.Sample_f(wo, out Vector3D wi, sampler.Get2D(), out double pdf, out BxdfType sampledType, type);

            // Return contribution of specular reflection
            Normal3D ns = isect.ShadingN;

            if (pdf > 0.0 && !f.IsBlack() && wi.AbsDot(ns) != 0.0)
            {
                // Compute ray differential _rd_ for specular reflection
                RayDifferential rd = new RayDifferential(isect.SpawnRay(wi));
                if (ray.HasDifferentials)
                {
                    rd.HasDifferentials = true;
                    rd.RxOrigin         = isect.P + isect.Dpdx.ToPoint3D();
                    rd.RyOrigin         = isect.P + isect.Dpdy.ToPoint3D();
                    // Compute differential reflected directions
                    Normal3D dndx = isect.ShadingDndu * isect.Dudx +
                                    isect.ShadingDndv * isect.Dvdx;
                    Normal3D dndy = isect.ShadingDndu * isect.Dudy +
                                    isect.ShadingDndv * isect.Dvdy;
                    Vector3D dwodx = -ray.RxDirection - wo,
                             dwody = -ray.RyDirection - wo;
                    double dDNdx   = dwodx.Dot(ns) + wo.Dot(dndx);
                    double dDNdy   = dwody.Dot(ns) + wo.Dot(dndy);
                    rd.RxDirection =
                        wi - dwodx + 2.0 * (wo.Dot(ns) * dndx + dDNdx * ns).ToVector3D();
                    rd.RyDirection =
                        wi - dwody + 2.0 * (wo.Dot(ns) * dndy + dDNdy * ns).ToVector3D();
                }
                return(f * Li(rd, scene, sampler, depth + 1) * wi.AbsDot(ns) /
                       pdf);
            }
            else
            {
                return(Spectrum.Create(0.0));
            }
        }
示例#4
0
        /// <inheritdoc />
        public override Spectrum We(Ray ray, out Point2D pRaster2)
        {
            // Interpolate camera matrix and check if $\w{}$ is forward-facing
            CameraToWorld.Interpolate(ray.Time, out Transform c2w);
            double cosTheta = ray.Direction.Dot(c2w.ExecuteTransform(new Vector3D(0.0, 0.0, 1.0)));

            if (cosTheta <= 0.0)
            {
                pRaster2 = null;
                return(Spectrum.Create(0.0));
            }

            // Map ray $(\p{}, \w{})$ onto the raster grid
            Point3D pFocus  = ray.AtPoint((LensRadius > 0.0 ? FocalDistance : 1.0) / cosTheta);
            Point3D pRaster = RasterToCamera.ExecuteTransform(c2w.Inverse().ExecuteTransform(pFocus));

            //Point3D pRaster = Inverse(RasterToCamera)(Inverse(c2w.Inverse)(pFocus));

            // Return raster position if requested
            pRaster2 = new Point2D(pRaster.X, pRaster.Y);

            // Return zero importance for out of bounds points
            Bounds2I sampleBounds = Film.GetSampleBounds();

            if (pRaster.X < sampleBounds.MinPoint.X || pRaster.Z >= sampleBounds.MaxPoint.X ||
                pRaster.Y < sampleBounds.MinPoint.Y || pRaster.Y >= sampleBounds.MaxPoint.Y)
            {
                return(Spectrum.Create(0.0));
            }

            // Compute lens area of perspective camera
            double lensArea = LensRadius != 0.0 ? (Math.PI * LensRadius * LensRadius) : 1.0;

            // Return importance for point on image plane
            double cos2Theta = cosTheta * cosTheta;

            return(Spectrum.Create(1.0 / (_a * lensArea * cos2Theta * cos2Theta)));
        }