public PrimarySampleSpacePathSampler()
 {
     SamplerState = PssmltSamplerState.WarmUp;
 }
        public override void InitPath(IPathProcessor buffer)
        {
            base.InitPath(buffer);
            this.scene = pathIntegrator.Scene;
            this.Radiance = new RgbSpectrum(0f);
            this.Throughput = new RgbSpectrum(1f);
            if (secRays == null)
                this.secRays = new ShadowRayInfo[scene.ShadowRayCount];
            if (pathIntegrator.Sampler.GetPass() > PssMltEngineController.WarmupIterations && SamplerState == PssmltSamplerState.WarmUp)
            {
                SamplerState = PssmltSamplerState.Initialize;
            }
        @restart:
            switch (SamplerState)
            {
                case PssmltSamplerState.WarmUp:
                    this.Sample = pathIntegrator.Sampler.GetSample();
                    this.Sample.InitSample(SamplesPerVertex * scene.MaxPathDepth);
                    this.contributionMap[this.Sample].Sample = this.Sample;
                    this.contributionMap[this.Sample].Weight = 1.0f;
                    break;
                case PssmltSamplerState.Initialize:
                    var s = pathIntegrator.Sampler.GetSample();
                    if (this.contributionMap[s].Sample != null)
                    {
                        this.Sample = this.contributionMap[s].Sample;
                    }
                    else
                    {
                        this.Sample.InitSample(SamplesPerVertex * scene.MaxPathDepth);
                        this.contributionMap[this.Sample].Sample = this.Sample;
                        this.contributionMap[this.Sample].Weight = 1.0f;
                    }
                    break;
                case PssmltSamplerState.LargeMutation:
                    s = pathIntegrator.Sampler.GetSample();
                    if (this.contributionMap[s].Sample != null)
                    {
                        this.Sample = this.contributionMap[s].Sample;
                    }
                    else
                    {
                        this.Sample = pathIntegrator.Sampler.GetSample();
                        this.Sample.InitSample(SamplesPerVertex * scene.MaxPathDepth);
                    }
                    this.mutationsCount = 0;
                    break;
                case PssmltSamplerState.SmallMutation:
                    mutationsCount++;
                    if (mutationsCount > PssMltEngineController.MaxMutations)
                    {
                        this.SamplerState = PssmltSamplerState.Initialize;
                        goto restart;
                    }
                    if (pathIntegrator.Sampler.GetLazyValue(this.Sample) < PssMltEngineController.LargeStepProbability)
                    {
                        this.SamplerState = PssmltSamplerState.LargeMutation;
                        goto restart;
                    }

                    if (this.XSample == null)
                        this.XSample = new Sample(this.Sample);
                    this.Sample = Mutate(this.Sample, mutationsCount, pathIntegrator.Sampler);
                    break;
            }
            RayData ray;
            if (Sample == null)
            {
                Debugger.Break();
            }
            pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out ray);
            this.PathRay = ray;
            this.RayIndex = -1;
            this.depth = 0;
            this.specularBounce = true;
        }
        public override void Splat(SampleBuffer sampleBuffer)
        {
            switch (SamplerState)
            {
                case PssmltSamplerState.LargeMutation:
                case PssmltSamplerState.Initialize:
                    sampleBuffer.SplatSample(this.Sample.imageX, this.Sample.imageY, ref Radiance);
                    if (!Radiance.IsBlack())
                    {
                        this.XContribution = Radiance;
                        this.XSample = new Sample(Sample);
                        this.SamplerState = PssmltSamplerState.SmallMutation;
                        this.mutationsCount = 0;
                    }
                    break;
                case PssmltSamplerState.SmallMutation:
                    if (!Radiance.IsBlack())
                    {
                        var yContrib = Radiance;
                        var yImportance = PssMltEngineController.Importance(ref yContrib);
                        var xImportance = PssMltEngineController.Importance(ref XContribution);

                        //if (!xImportance.NearEqual(yImportance))
                        //{
                        //    Debugger.Break();
                        //}
                        var a = Math.Min(1, (yImportance) / (xImportance));

                        var b_x = contributionMap[XSample].Radiance /Math.Max(1, contributionMap[XSample].Weight);
                        var b_y = contributionMap[this.Sample].Radiance / (Math.Max(1, contributionMap[Sample].Weight));

                        var xPixelContrib = ((1.0 - a) / (PssMltEngineController.MaxMutations)) * (XContribution / (xImportance / b_x));
                        var yPixelContrib = (a / PssMltEngineController.MaxMutations) * (yContrib / (yImportance / b_y));

                        sampleBuffer.SplatSample(XSample.imageX, XSample.imageY, ref xPixelContrib);
                        sampleBuffer.SplatSample(Sample.imageX, Sample.imageY, ref yPixelContrib);

                        contributionMap[XSample].Radiance += xPixelContrib;
                        contributionMap[Sample].Radiance += yPixelContrib;
                        //contributionMap[XSample].Weight += 1.0f;
                        //contributionMap[Sample] .Weight += 1.0f;


                        if (contributionMap.Rndf() < a)
                        {
                            this.XSample = new Sample(Sample);
                            this.XContribution = yContrib;
                        }
                    }
                    break;
                case PssmltSamplerState.WarmUp:
                    this.contributionMap[this.Sample].Radiance += Radiance;
                    this.contributionMap[this.Sample].Weight += 1.0f;
                    sampleBuffer.SplatSample(this.Sample.imageX, this.Sample.imageY, ref Radiance);
                    break;
            }
            this.InitPath(pathIntegrator);
        }