コード例 #1
0
        public Spectrum UniformSampleAllLights(Interaction inter, Scene scene, Sampler sampler)
        {
            var L = Spectrum.Zero;

            for (var l = 0; l < scene.Lights.Count; ++l)
            {
                var light = scene.Lights[l];

                // Estimate direct lighting using the requested sample arrays

                var lightPointArray = sampler.Get2DArray(lightSampleCounts[l]);
                var scatteringArray = sampler.Get2DArray(lightSampleCounts[l]);

                if (lightPointArray != null && scatteringArray != null)
                {
                    var Ld = Spectrum.Zero;
                    for (var sample = 0; sample < light.SampleCount; ++sample)
                    {
                        Ld += EstimateDirect(inter, scatteringArray[sample], light, lightPointArray[sample], scene, sampler);
                    }
                    L += Ld / light.SampleCount;
                }

                // If not available, fall back to single sample estimates

                else
                {
                    var lightPoint = sampler.Get2D();
                    var scattering = sampler.Get2D();
                    L += EstimateDirect(inter, scattering, light, lightPoint, scene, sampler);
                }
            }

            return(L);
        }
コード例 #2
0
        public Spectrum UniformSampleOneLight(Interaction inter, Scene scene, Sampler sampler)
        {
            if (!scene.Lights.Any())
            {
                return(Spectrum.Zero);
            }

            // Randomly choose a light
            var light = scene.Lights[Window.Random.Next(scene.Lights.Count)];

            // Compensate sampling a single light by multiplying the result by the light count
            // (will average the contribution of each light over enough samples)
            var lightPoint = sampler.Get2D();
            var scattering = sampler.Get2D();

            return(EstimateDirect(inter, scattering, light, lightPoint, scene, sampler) * scene.Lights.Count);
        }
コード例 #3
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);
        }
コード例 #4
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);
        }
コード例 #5
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));
            }
        }
コード例 #6
0
        private Spectrum SpecularReflect(RayDifferential ray, SurfaceInteraction inter, Scene scene, Camera camera, Sampler sampler, int depth)
        {
            // Sample a direction with the BSDF
            var type = BxDFType.Reflection | BxDFType.Specular;
            var f    = inter.Bsdf.Sample_f(inter.Wo, out Vector3 <float> wi, sampler.Get2D(), out float pdf, type, out BxDF.BxDFType sampledType);

            // Add the contribution of this reflection
            if (pdf > 0 && !f.IsBlack() && Vector3 <float> .AbsDot(wi, inter.Shading.N) != 0)
            {
                var newRay = inter.SpawnRay(wi).ToDiff();

                if (ray.HasDifferentials)
                {
                    // TODO
                }

                return(f * Li(newRay, scene, camera, sampler, depth + 1) * Vector3 <float> .AbsDot(wi, inter.Shading.N) * (1.0f / pdf));
            }

            return(Spectrum.Zero);
        }
コード例 #7
0
        public override Spectrum Li(RayDifferential ray, Scene scene, Camera camera, Sampler sampler, int depth = 0)
        {
            var L = Spectrum.Zero;

            // If the ray doesn't intersect the scene, return the background radiance
            if (!scene.Intersect(ray, out SurfaceInteraction inter) || inter == null)
            {
                foreach (var light in scene.Lights)
                {
                    L += light.Le(ray);
                }
                return(L);
            }

            // If the ray intersects something, we need to compute how the light is scattered

            var n  = inter.Shading.N;
            var wo = inter.Wo;

            inter.ComputeScatteringFunctions(ray);

            // Add the emissive contribution of the intersected object
            L += inter.Le(wo);

            // Add the direct contribution of each light source
            foreach (var light in scene.Lights)
            {
                // Sample the light source
                var Li = light.Sample_Li(inter, sampler.Get2D(), out Vector3 <float> wi, out float pdf, out VisibilityTester visibility);

                if (Li.IsBlack() || pdf == 0)
                {
                    continue;
                }

                // Evaluate the scattering at the interaction point
                var f = inter.Bsdf.f(wo, wi);

                // Trace a shadow ray to check that the point receives light
                if (!f.IsBlack())
                {
                    if (visibility.Unoccluded(scene))
                    {
                        L += f * Li * Vector3 <float> .AbsDot(wi, n.ToVector3()) * (1.0f / pdf);
                    }

                    /*else
                     *  L = new Spectrum(0, 0, 50);*/
                }
                else
                {
                }
            }

            // Recursively trace new rays
            if (depth + 1 < maxDepth)
            {
                L += SpecularReflect(ray, inter, scene, camera, sampler, depth);
                //L += SpecularTransmit(ray, inter, scene, sampler, depth);
            }

            return(L);
        }