コード例 #1
0
ファイル: RandomWalk.cs プロジェクト: pgrit/SeeSharp
        public virtual RgbColor StartFromEmitter(EmitterSample emitterSample, RgbColor initialWeight)
        {
            isOnLightSubpath = true;
            Ray ray = Raytracer.SpawnRay(emitterSample.Point, emitterSample.Direction);

            return(ContinueWalk(ray, emitterSample.Point, emitterSample.Pdf, initialWeight, 1));
        }
コード例 #2
0
ファイル: RandomWalk.cs プロジェクト: pgrit/SeeSharp
        public virtual RgbColor StartFromBackground(Ray ray, RgbColor initialWeight, float pdf)
        {
            isOnLightSubpath = true;

            // Find the first actual hitpoint on scene geometry
            var hit = scene.Raytracer.Trace(ray);

            if (!hit)
            {
                return(OnInvalidHit(ray, pdf, initialWeight, 1));
            }

            // Sample the next direction (required to know the reverse pdf)
            var(pdfNext, pdfReverse, weight, direction) = SampleNextDirection(hit, ray, initialWeight, 1);

            // Both pdfs have unit sr-1
            float pdfFromAncestor = pdf;
            float pdfToAncestor   = pdfReverse;

            RgbColor estimate = OnHit(ray, hit, pdfFromAncestor, initialWeight, 1, 1.0f);

            OnContinue(pdfToAncestor, 1);

            // Terminate if the maximum depth has been reached
            if (maxDepth <= 1)
            {
                return(estimate);
            }

            // Terminate absorbed paths and invalid samples
            if (pdfNext == 0 || weight == RgbColor.Black)
            {
                return(estimate);
            }

            // Continue the path with the next ray
            ray = Raytracer.SpawnRay(hit, direction);
            return(estimate + ContinueWalk(ray, hit, pdfNext, initialWeight * weight, 2));
        }
コード例 #3
0
ファイル: RandomWalk.cs プロジェクト: pgrit/SeeSharp
        RgbColor ContinueWalk(Ray ray, SurfacePoint previousPoint, float pdfDirection, RgbColor throughput,
                              int depth)
        {
            // Terminate if the maximum depth has been reached
            if (depth >= maxDepth)
            {
                OnTerminate();
                return(RgbColor.Black);
            }

            var hit = scene.Raytracer.Trace(ray);

            if (!hit)
            {
                var result = OnInvalidHit(ray, pdfDirection, throughput, depth);
                OnTerminate();
                return(result);
            }

            // Convert the PDF of the previous hemispherical sample to surface area
            float pdfFromAncestor = pdfDirection * SampleWarp.SurfaceAreaToSolidAngle(previousPoint, hit);

            // Geometry term might be zero due to, e.g., shading normal issues
            // Avoid NaNs in that case by terminating early
            if (pdfFromAncestor == 0)
            {
                OnTerminate();
                return(RgbColor.Black);
            }

            RgbColor estimate = OnHit(ray, hit, pdfFromAncestor, throughput, depth,
                                      SampleWarp.SurfaceAreaToSolidAngle(hit, previousPoint));

            // Terminate with Russian roulette
            float survivalProb = ComputeSurvivalProbability(hit, ray, throughput, depth);

            if (rng.NextFloat() > survivalProb)
            {
                OnTerminate();
                return(estimate);
            }

            // Continue based on the splitting factor
            int numSplits = ComputeSplitFactor(hit, ray, throughput, depth);

            for (int i = 0; i < numSplits; ++i)
            {
                // Sample the next direction and convert the reverse pdf
                var(pdfNext, pdfReverse, weight, direction) = SampleNextDirection(hit, ray, throughput, depth);
                float pdfToAncestor = pdfReverse * SampleWarp.SurfaceAreaToSolidAngle(hit, previousPoint);

                if (pdfToAncestor == 0)
                {
                    Debug.Assert(pdfNext == 0);
                }

                OnContinue(pdfToAncestor, depth);

                if (pdfNext == 0 || weight == RgbColor.Black)
                {
                    OnTerminate();
                    continue;
                }

                // Account for splitting and roulette in the weight
                weight *= 1.0f / (survivalProb * numSplits);

                // Continue the path with the next ray
                var nextRay = Raytracer.SpawnRay(hit, direction);
                estimate += ContinueWalk(nextRay, hit, pdfNext, throughput * weight, depth + 1);
            }

            return(estimate);
        }