예제 #1
0
        public override void InitPath(IPathProcessor buffer)
        {
            base.InitPath(buffer);
            this.scene = pathIntegrator.Scene;
            this.Radiance = new RgbSpectrum(0f);
            this.waveRadiance = 0f;
            this.waveThroughput = 1f;
            this.PathState = PathTracerPathState.EyeVertex;
            if (this.secRays == null)
                this.secRays = new ShadowRayInfo[scene.ShadowRaysPerSample];

            if (lambdaSample == 0)
            {
                this.Sample = pathIntegrator.Sampler.GetSample(this.Sample);
                this.Sample.InitSample(scene.MaxPathDepth*8);
                pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out this.PathRay);
            }

            this.HeroWavelength = this.wlSampler.SampleWavelength(
                lambdaSample);
                //Sample.GetLazyValue(0));
            this.RayIndex = -1;
            this.pathWeight = 1.0f;
            this.tracedShadowRayCount = 0;
            this.depth = 0;
            this.specularBounce = true;
        }
예제 #2
0
        public override void InitPath(IPathProcessor buffer)
        {
            base.InitPath(buffer);
            this.scene = pathIntegrator.Scene;
            this.PathState = PathTracerPathState.EyeVertex;
            if (this.secRays == null)
                this.secRays = new ConnectRayInfo[MaxEyeRays];
            this.RayIndex = -1;
            this.pathWeight = 1.0f;
            this.tracedShadowRayCount = 0;
            this.depth = 0;
            this.specularBounce = true;
            this.Radiance = new RgbSpectrum(0f);

            this.Sample = pathIntegrator.Sampler.GetSample(null);
            LightSample ls;
            var light = scene.Lights[scene.SampleLights(Sample.GetLazyValue())];
            light.EvaluatePhoton(scene, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), out ls);
            PathRay = ls.LightRay;
            var lightPdf = ls.Pdf;
            Throughput = (RgbSpectrum)(ls.Spectrum);
            //* scene.Lights.Length) / lightPdf;

            //buffer.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out this.PathRay);
        }
예제 #3
0
 public override void InitPath(IPathProcessor buffer)
 {
     base.InitPath(buffer);
     this.scene = pathIntegrator.Scene;
     this.Radiance = new RgbSpectrum(0f);
     this.Throughput = new RgbSpectrum(1f);
     this.PathState = PathTracerPathState.EyeVertex;
     if (this.secRays == null)
         this.secRays = new ShadowRayInfo[scene.ShadowRayCount];
     if (this.volumeComp == null)
     {
         this.volumeComp = scene.GetVolumeComputation();
     }
     else
     {
         this.volumeComp.Reset();
     }
     this.Sample = pathIntegrator.Sampler.GetSample(null);
     IRay ray;
     pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out ray);
     this.PathRay = (RayData)ray;
     this.RayIndex = -1;
     this.pathWeight = 1.0f;
     this.tracedShadowRayCount = 0;
     this.depth = 0;
     this.specularBounce = true;
     this.rayID = (int)(Sample.imageX + Sample.imageY * 640f);
 }
예제 #4
0
 public override void InitPath(IPathProcessor buffer)
 {
     base.InitPath(buffer);
     this.scene = pathIntegrator.Scene;
     this.Radiance = new RgbSpectrum(0f);
     this.Throughput = new RgbSpectrum(1f);
     this.PathState = PathTracerPathState.EyeVertex;
     if (this.secRays == null)
     {
         this.secRays = new ShadowRayInfo[scene.ShadowRaysPerSample];
         continueRays = new ShadowRayInfo[scene.ShadowRaysPerSample];
     }
     if (volumeComp == null)
     {
         volumeComp = new VolumeComputation(scene.VolumeIntegrator);
     }
     contCount = 0;
     this.Sample = pathIntegrator.Sampler.GetSample(this.Sample);
     pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out this.PathRay);
     this.RayIndex = -1;
     this.pathWeight = 1.0f;
     this.tracedShadowRayCount = 0;
     this.depth = 0;
     this.specularBounce = true;
     this.inVolume = false;
 }
예제 #5
0
 public override void InitPath(IPathProcessor buffer)
 {
     base.InitPath(buffer);
     if (secRays == null)
     {
         secRays = new ShadowRayInfo[scene.ShadowRayCount];
     }
     PathState = PathTracerPathState.EyeVertex;
 }
예제 #6
0
 public override void InitPath(PathBuffer buffer) {
     base.InitPath(buffer);
     this.scene = buffer.Scene;
     this.Radiance = new RgbSpectrum(0f);
     this.Throughput = new RgbSpectrum(1f);
     this.PathState = PathTracerPathState.EyeVertex;
     this.Sample = buffer.Sampler.GetSample();
     this.PathRay = new RayData ( scene.Camera.GetRay(Sample.imageX, Sample.imageY));
     this.RayIndex = -1;
     this.pathWeight = 1.0f;
     this.tracedShadowRayCount = 0;
     this.depth = 0;
     this.specularBounce = true;
 }
 public override void InitPath(IPathProcessor buffer)
 {
     base.InitPath(buffer);
     this.scene = pathIntegrator.Scene;
     this.Radiance = new SampledSpectrum(0f);
     this.Throughput = new SampledSpectrum(1f);
     this.PathState = PathTracerPathState.EyeVertex;
     if (this.secRays == null)
         this.secRays = new SpectralShadowRayInfo[scene.ShadowRaysPerSample];
     this.Sample = pathIntegrator.Sampler.GetSample(null);
     pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out this.PathRay);
     this.RayIndex = -1;
     this.pathWeight = 1.0f;
     this.tracedShadowRayCount = 0;
     this.depth = 0;
     this.specularBounce = true;
 }
예제 #8
0
        public override void InitPath(IPathProcessor buffer)
        {
            base.InitPath(buffer);
            this.scene = pathIntegrator.Scene;

            if (Vertices == null)
            {
                Vertices = new PathVertex[scene.MaxPathDepth * 3];
                Xvertices = new PathVertex[scene.MaxPathDepth * 3];
            }
            this.pathDensity = 1.0f;
            this.Radiance = new RgbSpectrum(0f);
            this.Throughput = new RgbSpectrum(1f);
            this.PathState = PathTracerPathState.EyeVertex;
            if (!mutate)
            {
                this.Sample = pathIntegrator.Sampler.GetSample(this.Sample);
                pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out this.PathRay);
                pathStart = PathRay.Org;
                XRadiance = new RgbSpectrum();
                xPathDensity = 1.0f;
            }
            else
            {
                PathRay.Org = pathStart;
                PathRay.Dir = -Vertices[0].Wo;
                this.BackupPath();
                this.MutatePath();
                mutationCount++;
                if (mutationCount > MaxMutations)
                {
                    this.mutate = false;
                    this.mutationCount = 0;
                    this.InitPath(buffer);
                }
            }
            this.RayIndex = -1;
            this.depth = 0;
            this.bsdfEvent = BsdfEvent.Specular;
            this.prevEvent = BsdfEvent.None;
            shadowRayEvent = BsdfEvent.None;
        }
예제 #9
0
        public override void InitPath(IPathProcessor buffer)
        {
            base.InitPath(buffer);
            this.scene = pathIntegrator.Scene;
            this.Radiance = new RgbSpectrum(0f);
            this.Throughput = new RgbSpectrum(1f);
            this.PathState = PathTracerPathState.EyeVertex;
            if (this.secRays == null)
            {
                this.secRays = new ShadowRayInfo[scene.ShadowRaysPerSample];
                continueRays = new ShadowRayInfo[scene.ShadowRaysPerSample];
            }
            if (paths == null)
            {
                paths = new List<PathInfo>();
            }
            if (CurrentVertices == null)
            {
                CurrentVertices = new List<PathVertex>();
            }
            else
            {
                CurrentVertices.Clear();
            }

            contCount = 0;
            this.Sample = pathIntegrator.Sampler.GetSample(this.Sample);

            pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out this.PathRay);
            this.EyeSample = new CameraSample()
            {
                imageX = (float)Sample.imageX,
                imageY = (float)Sample.imageY,
                EyeRay = this.PathRay
            };
            this.RayIndex = -1;
            this.pathWeight = 1.0f;
            this.tracedShadowRayCount = 0;
            this.depth = 0;
            this.specularBounce = true;
        }
예제 #10
0
        public override void InitPath(IPathProcessor buffer)
        {
            base.InitPath(buffer);
            this.scene = pathIntegrator.Scene;
            this.Radiance = new RgbSpectrum(0f);
            this.Throughput = new RgbSpectrum(1f);
            this.PathState = PathTracerPathState.EyeVertex;
            this.secRays = new ShadowRayInfo[scene.ShadowRayCount];
            this.sampler = (MarkovChainSampler)pathIntegrator.Sampler;

            this.Sample = this.sampler.EvalNextSample(this.Sample, xImportance);
            IRay ray;
            pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out ray);
            this.PathRay = (RayData)ray;
            this.RayIndex = -1;
            this.pathWeight = 1.0f;

            this.tracedShadowRayCount = 0;
            this.depth = 0;
            this.specularBounce = true;
        }
예제 #11
0
 public override void InitPath(IPathProcessor buffer)
 {
     base.InitPath(buffer);
     this.scene = pathIntegrator.Scene;
     this.Radiance = new RgbSpectrum(0f);
     this.Throughput = new RgbSpectrum(1f);
     this.PathState = PathTracerPathState.EyeVertex;
     if (this.secRays == null)
     {
         this.secRays = new ShadowRayInfo[scene.ShadowRaysPerSample+10];
         continueRays = new ShadowRayInfo[scene.ShadowRaysPerSample+10];
     }
     contCount = 0;
     this.Sample = pathIntegrator.Sampler.GetSample(this.Sample);
     pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out this.PathRay);
     this.RayIndex = -1;
     this.tracedShadowRayCount = 0;
     this.depth = 0;
     this.bsdfEvent = BsdfEvent.Specular;
     this.prevEvent = BsdfEvent.None;
     shadowRayEvent = BsdfEvent.None;
 }
예제 #12
0
        public override sealed void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
            int currentTriangleIndex = 0;
#if VERBOSE

            try {
#endif

            if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                (tracedShadowRayCount > 0))
            {
                for (int i = 0; i < tracedShadowRayCount; ++i)
                {
                    RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].ShadowRayIndex];
                    RgbSpectrum attenuation;
                    bool continueTrace;
                    if (this.VolumeShadowRayTest(ref shadowRayHit, ref secRays[i].ShadowRay, out attenuation, out continueTrace))
                    {
                        Radiance += attenuation * ((secRays[i].Throughput) / secRays[i].Pdf);
                        pathWeight *= secRays[i].Pdf;
                    }

                    if (continueTrace)
                    {
                        continueRays[contCount++] = secRays[i];
                        //continueRays.Add(secRays[i]);
                    }
                }

                if (PathState == PathTracerPathState.ShadowRaysOnly)
                {
                    Splat(consumer);
                    return;
                }

                Array.Copy(continueRays, secRays, contCount);
                tracedShadowRayCount = contCount;
                contCount = 0;
            }
            RayHit rayHit = rayBuffer.rayHits[RayIndex];
            Vector wo = -PathRay.Dir;

            depth++;
            bool missed = rayHit.Index == 0xffffffffu;
            if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
            {
                if (missed)
                {
                    //Radiance += this.scene.SampleEnvironment(ref wo) * Throughput;
                    var sampledEnvironment = this.scene.SampleEnvironment(ref wo);
                    Radiance.MAdd(ref sampledEnvironment, ref Throughput);
                }
                Splat(consumer);

                return;
            }

            //var mesh = scene.GetMeshByTriangleIndex(currentTriangleIndex);
            //rayHit.Index += (uint)mesh.StartTriangle;
            // Something was hit
            if (hitInfo == null)
            {
                hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit);
            }
            else
            {
                SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo);
            }
            currentTriangleIndex = (int)rayHit.Index;

            if (hitInfo == null)
            {
                Debugger.Break();
            }
            //If Hit light)

            if (hitInfo.IsLight)
            {
                if (specularBounce || depth == 1)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);
                    if (lt != null)
                    {
                        float pdf;
                        var le = hitInfo.Color * lt.Emittance(ref wo, out pdf);
                        //Radiance += Throughput * le;

                        Radiance.MAdd(ref Throughput, ref le);
                    }
                }
                Splat(consumer);

                return;
            }
            var hitPoint = PathRay.Point(rayHit.Distance);
            if (inVolume && !hitInfo.isVolume)
            {
                Throughput *= Math.Exp(-rayHit.Distance*0.1f);
            }

            inVolume = false;
            if (hitInfo.isVolume)
            {


                //if (Sample.GetLazyValue() <= scene.VolumeIntegrator.GetRRProbability())
                //{
                //    RayData volumeRay = new RayData(ref PathRay.Org, ref PathRay.Dir, 0f,
                //                                    rayHit.Miss() ? 1e10f : rayHit.Distance);
                //    scene.VolumeIntegrator.GenerateLiRays(scene, Sample, ref volumeRay, volumeComp);
                //    Radiance += volumeComp.GetEmittedLight();

                //    if (volumeComp.GetRayCount() > 0)
                //    {
                //        PathState = PathTracerPathState.EyeVolume;
                //        rayHit = (rayBuffer.rayHits[RayIndex]);
                //    }
                //}

                inVolume = true;
                RgbSpectrum sigma_s = hitInfo.VolumeData.Scattering;
                RgbSpectrum sigma_a = hitInfo.VolumeData.Absorbance;
                RgbSpectrum sigma_e = hitInfo.VolumeData.Emittance;

                var distance = SampleDistance(Sample.GetLazyValue(), sigma_s.y());
                hitPoint = PathRay.Point(rayHit.Distance + distance);
                var eventEps = Sample.GetLazyValue();

                if (eventEps > (sigma_a.y() + sigma_e.y() + sigma_e.y()))
                {
                    Throughput *= RgbSpectrum.Exp(-distance * sigma_s);
                    PathRay.Org = hitPoint;
                    PathState = PathTracerPathState.NextVertex;
                    return;
                }

                if (sigma_e.y() > 0f && eventEps > sigma_e.y())
                {
                    Radiance += Throughput * sigma_e;
                    Splat(consumer);
                    return;
                }

                if (eventEps < sigma_a.y())
                {
                    Radiance += Throughput * sigma_a;
                    if (tracedShadowRayCount > 0)
                    {
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    }
                    else
                    {
                        Splat(consumer);

                        return;
                    }

                }
                else //if (eventEps > sigma_a.y() )
                {
                    var pdf = 1f - MathLab.Exp(-sigma_s.y() * distance);
                    var vwi = new Vector(Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue());
                    var fp = PhaseFunctions.PhaseIsotropic(ref wo, ref vwi);


                    Throughput *= (fp * ((sigma_s+sigma_a)*0.5f) );
                    PathRay.Org = hitPoint + wo * distance;
                    PathRay.Dir = vwi.Normalize();
                    PathState = PathTracerPathState.NextVertex;
                    return;
                }
            }


            tracedShadowRayCount = 0;
            var bsdf = hitInfo.MMaterial;

            if (!hitInfo.TextureData.Alpha.IsBlack())
            {
                Throughput *= (RgbSpectrum.UnitSpectrum() - (RgbSpectrum)hitInfo.TextureData.Alpha);
                PathRay = new RayData(hitPoint, -wo);
                return;
            }

            if (bsdf.IsDiffuse())
            {
                float lightStrategyPdf = LightSampler.StrategyPdf;
                //scene.ShadowRaysPerSample/(float)scene.Lights.Length;
                RgbSpectrum lightTroughtput = Throughput * hitInfo.Color;
                LightSampler.EvaluateShadow(ref hitPoint, ref hitInfo.Normal, Sample.GetLazyValue(),
                                            Sample.GetLazyValue(), Sample.GetLazyValue(), ref ls);
                for (int index = 0; index < ls.Length; index++)
                {

                    if (ls[index].Pdf <= 0f)
                        continue;
                    secRays[tracedShadowRayCount].Throughput = ls[index].Spectrum.GetType() == typeof(RgbSpectrumInfo) ? (RgbSpectrum)(RgbSpectrumInfo)ls[index].Spectrum : (RgbSpectrum)ls[index].Spectrum;
                    secRays[tracedShadowRayCount].Pdf = ls[index].Pdf;
                    secRays[tracedShadowRayCount].ShadowRay = ls[index].LightRay;
                    Vector lwi = secRays[tracedShadowRayCount].ShadowRay.Dir;
                    RgbSpectrum fs;
                    hitInfo.MMaterial.f(ref secRays[tracedShadowRayCount].ShadowRay.Dir, ref wo, ref hitInfo.ShadingNormal, ref Throughput, out fs, types: BrdfType.Diffuse);
                    secRays[tracedShadowRayCount].Throughput *= lightTroughtput *
                                                                Vector.AbsDot(ref hitInfo.Normal, ref lwi) *
                                                                fs;
                    if (!secRays[tracedShadowRayCount].Throughput.IsBlack())
                    {
#if DEBUG
                        RayDen.Library.Core.Components.Assert.IsNotNaN(secRays[tracedShadowRayCount].Pdf);
#endif
                        secRays[tracedShadowRayCount].Pdf /= lightStrategyPdf;
                        tracedShadowRayCount++;
                    }
                }
            }

            float fPdf = 0f;
            var wi = new Vector();
            RgbSpectrum f;
            hitInfo.TextureData.Throughput = Throughput;
            f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                                Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue()
                                , ref hitInfo.TextureData, out fPdf, out specularBounce);

            if ((fPdf <= 0.0f) || f.IsBlack())
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);

                }
                return;
            }
            pathWeight *= fPdf;
            Throughput *= (f * hitInfo.Color) / fPdf;

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue())
                {
                    Throughput /= prob;
                    pathWeight *= prob;
                }
                else
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;

#if VERBOSE
            }
            catch (Exception ex) {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #13
0
        public override sealed void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
             int currentTriangleIndex = 0;
#if VERBOSE

            try {
#endif

            if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                (tracedShadowRayCount > 0))
            {
                for (int i = 0; i < tracedShadowRayCount; ++i)
                {
                    RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].ShadowRayIndex];
                    RgbSpectrum attenuation;
                    bool continueTrace;
                    if (this.ShadowRayTest(ref shadowRayHit, ref secRays[i].ShadowRay, out attenuation, out continueTrace))
                    {

                        Radiance += attenuation * ((secRays[i].Throughput) / secRays[i].Pdf);
                        pathWeight *= secRays[i].Pdf;
                    }

                    if (continueTrace)
                    {
                        continueRays[contCount++] = secRays[i];
                        //continueRays.Add(secRays[i]);
                    }
                }

                if (PathState == PathTracerPathState.ShadowRaysOnly)
                {
                    Splat(consumer);
                    return;
                }

                Array.Copy(continueRays, secRays, contCount);
                tracedShadowRayCount = contCount;
                contCount = 0;
            }
            RayHit rayHit = rayBuffer.rayHits[RayIndex];
            Vector wo = -PathRay.Dir;

            depth++;
            bool missed = rayHit.Index == 0xffffffffu;
            if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
            {
                if (missed)
                {
                    //Radiance += this.scene.SampleEnvironment(ref wo) * Throughput;
                    var sampledEnvironment = this.scene.SampleEnvironment(ref wo);
                    Radiance.MAdd(ref sampledEnvironment , ref Throughput);
                }
                Splat(consumer);

                return;
            }

            //var mesh = scene.GetMeshByTriangleIndex(currentTriangleIndex);
            //rayHit.Index += (uint)mesh.StartTriangle;
            // Something was hit
            if (hitInfo == null)
            {
                hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit);
            }
            else
            {
                SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo);
            }
            currentTriangleIndex = (int)rayHit.Index;

            if (hitInfo == null)
            {
                Debugger.Break();
            }
            //If Hit light)

            if (hitInfo.IsLight)
            {
                if (specularBounce || depth == 1)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);
                    if (lt != null)
                    {
                        float pdf;
                        var le = hitInfo.Color * lt.Emittance(ref wo, out pdf);
                        //Radiance += Throughput * le;
                        
                        Radiance.MAdd(ref Throughput, ref le);
                    }
                }
                Splat(consumer);

                return;
            }

            var hitPoint = PathRay.Point(rayHit.Distance);

            tracedShadowRayCount = 0;
            var bsdf = hitInfo.MMaterial;

            if (!hitInfo.TextureData.Alpha.IsBlack())
            {
                Throughput *= (RgbSpectrum.UnitSpectrum() - (RgbSpectrum) hitInfo.TextureData.Alpha);
                PathRay = new RayData(hitPoint, -wo);
                return;
            }

            if (bsdf.IsDiffuse())
            {
                float lightStrategyPdf = LightSampler.StrategyPdf;
                //scene.ShadowRaysPerSample/(float)scene.Lights.Length;
                RgbSpectrum lightTroughtput = Throughput * hitInfo.Color;
                LightSampler.EvaluateShadow(ref hitPoint, ref hitInfo.Normal, Sample.GetLazyValue(),
                                            Sample.GetLazyValue(), Sample.GetLazyValue(), ref ls);
                for (int index = 0; index < ls.Length; index++)
                {

                    if (ls[index].Pdf <= 0f)
                        continue;
                    secRays[tracedShadowRayCount].Throughput = ls[index].Spectrum.GetType() == typeof(RgbSpectrumInfo) ? (RgbSpectrum) (RgbSpectrumInfo)ls[index].Spectrum : (RgbSpectrum)ls[index].Spectrum;
                    secRays[tracedShadowRayCount].Pdf = ls[index].Pdf;
                    secRays[tracedShadowRayCount].ShadowRay = ls[index].LightRay;
                    Vector lwi = secRays[tracedShadowRayCount].ShadowRay.Dir;
                    RgbSpectrum fs;
                    hitInfo.MMaterial.f(ref secRays[tracedShadowRayCount].ShadowRay.Dir, ref wo, ref hitInfo.ShadingNormal, ref Throughput, out fs, types: BrdfType.Diffuse);
                    secRays[tracedShadowRayCount].Throughput *= lightTroughtput *
                                                                Vector.AbsDot(ref hitInfo.Normal, ref lwi) *
                                                                fs;
                    if (!secRays[tracedShadowRayCount].Throughput.IsBlack())
                    {
#if DEBUG
                        RayDen.Library.Core.Components.Assert.IsNotNaN(secRays[tracedShadowRayCount].Pdf);
#endif
                        secRays[tracedShadowRayCount].Pdf /= lightStrategyPdf;
                        LightSample = ls[index];
                        tracedShadowRayCount++;
                    }
                }
            }

            float fPdf = 0f;
            var wi = new Vector();
            RgbSpectrum f;
            hitInfo.TextureData.Throughput = Throughput;
            f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                                Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue()
                                , ref hitInfo.TextureData, out fPdf, out specularBounce);

            if ((fPdf <= 0.0f) || f.IsBlack())
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);

                }
                return;
            }
            CurrentVertices.Add(new PathVertex()
            {
                BsdfPdf = fPdf,
                Throughput = Throughput,
                GeoNormal = hitInfo.Normal,
                HitPoint = hitPoint,
                HitType = PathVertexType.Geometry,
                IncomingDirection = wi,
                Material = bsdf,
                OutgoingDirection = wo,
                RayDistance = rayHit.Distance,
                SampleU = rayHit.U,
                SampleV = rayHit.V,
                ShadingNormal = hitInfo.ShadingNormal,
                TexCoords = hitInfo.TexCoords,
                rrWeight = 1f,
            });
            pathWeight *= fPdf;
            Throughput *= (f * hitInfo.Color) / fPdf;

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue())
                {
                    CurrentVertices[CurrentVertices.Count - 1].rrWeight = 1f/prob;
                    Throughput /= prob;
                    pathWeight *= prob;
                }
                else
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;


#if VERBOSE
            }
            catch (Exception ex) {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #14
0
        public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
             int currentTriangleIndex = 0;
#if VERBOSE

            try {
#endif

            if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                (tracedShadowRayCount > 0))
            {
                for (int i = 0; i < tracedShadowRayCount; ++i)
                {
                    RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].ShadowRayIndex];
                    RgbSpectrum attenuation;
                    bool continueTrace;
                    if (this.ShadowRayTest(ref shadowRayHit, ref secRays[i].ShadowRay, out attenuation, out continueTrace))
                    {
                        //if (prevEvent.Has(BsdfEvent.Transmit) && bsdfEvent.Has(BsdfEvent.Transmit))
                        //{
                        //    attenuation*= hitInfo.Color * MathLab.Exp(-Math.Max(shadowRayHit.Distance, Sample.GetLazyValue()*10f));
                        //}
                        Radiance += attenuation * ((secRays[i].Throughput) / secRays[i].Pdf);
                    }

                    if (continueTrace)
                    {
                        continueRays[contCount++] = secRays[i];
                        //continueRays.Add(secRays[i]);
                    }
                }

                if (PathState == PathTracerPathState.ShadowRaysOnly)
                {
                    Splat(consumer);
                    return;
                }

                Array.Copy(continueRays, secRays, contCount);
                tracedShadowRayCount = contCount;
                contCount = 0;
            }
            RayHit rayHit = rayBuffer.rayHits[RayIndex];
            Vector wo = -PathRay.Dir;

            depth++;
            bool missed = rayHit.Index == 0xffffffffu;
            if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
            {
                if (missed)
                {
                    //Radiance += this.scene.SampleEnvironment(ref wo) * Throughput;
                    var sampledEnvironment = this.scene.SampleEnvironment(ref wo);
                    Radiance.MAdd(ref sampledEnvironment , ref Throughput);
                }
                Splat(consumer);

                return;
            }

            var bsdf = SurfaceSampler.GetBsdf(ref PathRay, ref rayHit, ref currentMedium, false, this.Sample.GetLazyValue());

            //var mesh = scene.GetMeshByTriangleIndex(currentTriangleIndex);
            //rayHit.Index += (uint)mesh.StartTriangle;
            // Something was hit

            currentTriangleIndex = (int)rayHit.Index;

            
            //If Hit light)

            if (bsdf.IsLightSource())
            {
                //if (bsdfEvent.Has(BsdfEvent.Specular) || depth == 1)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);
                    if (lt != null)
                    {
                        float pdf;
                        var le = lt.Emittance(ref wo, out pdf);
                        //Radiance += Throughput * le;
                        
                        Radiance.MAdd(ref Throughput, ref le);
                    }
                }
                Splat(consumer);

                return;
            }

            var hitPoint = PathRay.Point(rayHit.Distance);

            tracedShadowRayCount = 0;
            

            if (bsdf.IsDiffuse())
            {
                float lightStrategyPdf = LightSampler.StrategyPdf;
                //scene.ShadowRaysPerSample/(float)scene.Lights.Length;
                RgbSpectrum lightTroughtput = Throughput*(RgbSpectrum) bsdf.TexData.Diffuse;
                LightSampler.EvaluateShadow(bsdf, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), ref ls);
                for (int index = 0; index < ls.Length; index++)
                {

                    if (ls[index].Pdf <= 0f)
                        continue;
                    secRays[tracedShadowRayCount].Throughput = ls[index].Spectrum.GetType() == typeof(RgbSpectrumInfo) ? (RgbSpectrum) (RgbSpectrumInfo)ls[index].Spectrum : (RgbSpectrum)ls[index].Spectrum;
                    secRays[tracedShadowRayCount].Pdf = ls[index].Pdf;
                    secRays[tracedShadowRayCount].ShadowRay = ls[index].LightRay;
                    Vector lwi = secRays[tracedShadowRayCount].ShadowRay.Dir;
                    BsdfEvent devent;
                    float pdfw, ipdfw;
                    var fs = (RgbSpectrum)bsdf.Evaluate(ref lwi, out devent, out pdfw, out ipdfw);
                    if (pdfw < MathLab.Epsilon)
                        continue;
                    secRays[tracedShadowRayCount].Throughput *= lightTroughtput * ((fs
                                                                * Vector.AbsDot(ref bsdf.HitPoint.ShadingNormal, ref lwi)));
                    if (!secRays[tracedShadowRayCount].Throughput.IsBlack())
                    {
#if DEBUG
                        RayDen.Library.Core.Components.Assert.IsNotNaN(secRays[tracedShadowRayCount].Pdf);
#endif
                        secRays[tracedShadowRayCount].Pdf *= lightStrategyPdf * pdfw;
                        secRays[tracedShadowRayCount].Pdf *= scene.ShadowRayCount;
                        tracedShadowRayCount++;
                    }
                }
            }

            float fPdf, frPdf;
            Vector wi;
            RgbSpectrum f;
            prevEvent = bsdfEvent;

            f =
                    bsdf.Sample(out wi, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), out fPdf,
                        out frPdf, out bsdfEvent);

            //if (prevEvent.Has(BsdfEvent.Transmit))
            //{
            //    Throughput *= MathLab.Exp(-rayHit.Distance)*0.1f;
            //}

            if (prevEvent.Has(BsdfEvent.Transmit) && bsdfEvent.Has(BsdfEvent.Transmit))
            {
                Throughput *= MathLab.Exp(-rayHit.Distance)*0.2f;
            }


            if ((fPdf <= 0.0f) || f.IsBlack())
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);

                }
                return;
            }
            Throughput *= (f * (RgbSpectrum)bsdf.HitPoint.Color) / fPdf;//* (RgbSpectrum)bsdf.HitPoint.Color

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue())
                {
                    Throughput /= prob;
                }
                else
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;


#if VERBOSE
            }
            catch (Exception ex) {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #15
0
        public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
            int currentTriangleIndex = 0;
            SurfaceIntersectionData hitInfo = null;
#if VERBOSE

            try
            {
#endif

                base.Advance(rayBuffer, consumer);

                RayHit rayHit = rayBuffer.rayHits[RayIndex];

                if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                    (tracedShadowRayCount > 0))
                {
                    for (int i = 0; i < tracedShadowRayCount; ++i)
                    {
                        RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].currentShadowRayIndex];
                        RgbSpectrum attenuation;
                        if (this.ShadowRayTest(ref shadowRayHit, out attenuation))
                        {
                            //                            Radiance.MADD()
                            mutate = true;
                            Radiance += attenuation * ((secRays[i].color));
                            pathWeight *= secRays[i].pdf;
                        }
                    }
                    Splat(consumer);

                    return;
                }

                depth++;
                bool missed = rayHit.Index == 0xffffffffu;
                if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
                {
                    if (specularBounce && missed)
                    {
                        Radiance += this.SampleEnvironment(PathRay.Dir) * Throughput;
                    }
                    Splat(consumer);

                    return;
                }

                // Something was hit
                hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit);
                currentTriangleIndex = (int)rayHit.Index;

                if (hitInfo == null)
                {
                    Debugger.Break();
                }
                //If Hit light)
                if (hitInfo.IsLight)
                {
                    if (specularBounce)
                    {
                        var lt = scene.GetLightByIndex(currentTriangleIndex);
                        if (lt != null)
                        {
                            var le = (RgbSpectrum)(lt.Le(ref PathRay.Dir));
                            Radiance += Throughput * le;
                            mutate = true;
                        }
                    }
                    Splat(consumer);

                    return;
                }

                var hitPoint = PathRay.Point(rayHit.Distance);

                Vector wo = -PathRay.Dir;
                tracedShadowRayCount = 0;
                if (hitInfo.MMaterial.IsDiffuse())
                {
                    float lightStrategyPdf = 1f;// scene.ShadowRayCount / (float)scene.Lights.Length;
                    RgbSpectrum lightTroughtput = Throughput * hitInfo.Color;
                    for (int i = 0; i < scene.ShadowRayCount; ++i)
                    {
                        int currentLightIndex = scene.SampleLights(Sample.GetLazyValue(depth * 0));
                        var light = scene.Lights[currentLightIndex];

                        var ls = new LightSample();
                        light.EvaluateShadow(ref hitPoint, ref hitInfo.ShadingNormal, Sample.GetLazyValue(depth * 1), Sample.GetLazyValue(depth * 2), Sample.GetLazyValue(depth * 3), ref ls);
                        if (ls.Pdf <= 0f)
                        {
                            continue;
                        }

                        secRays[tracedShadowRayCount].color = (RgbSpectrum)(ls.Spectrum);
                        secRays[tracedShadowRayCount].pdf = ls.Pdf;
                        secRays[tracedShadowRayCount].shadowRay = ls.LightRay;

                        Vector lwi = secRays[tracedShadowRayCount].shadowRay.Dir;
                        RgbSpectrum fs;
                        hitInfo.MMaterial.f(
                            ref secRays[tracedShadowRayCount].shadowRay.Dir,
                            ref wo, ref hitInfo.ShadingNormal, ref Throughput, out fs, types: BrdfType.Diffuse);
                        secRays[tracedShadowRayCount].color *= lightTroughtput *
                                                               Vector.AbsDot(ref hitInfo.ShadingNormal, ref lwi) *
                                                               fs;
                        if (!secRays[tracedShadowRayCount].color.IsBlack())
                        {
                            secRays[tracedShadowRayCount].pdf *= lightStrategyPdf;
                            tracedShadowRayCount++;
                        }
                    }
                }

                float fPdf;
                Vector wi;

                RgbSpectrum f = hitInfo.MMaterial.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                                                          Sample.GetLazyValue(depth * 4), Sample.GetLazyValue(depth * 5),
                                                          Sample.GetLazyValue(depth * 6), ref hitInfo.TextureData, 
                                                          out fPdf, out specularBounce);

                if ((fPdf <= 0.0f) || f.IsBlack())
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }
                    return;
                }
                pathWeight *= fPdf;
                Throughput *= f / fPdf;
                if (!mutate)
                    mutate = Throughput.Filter() > Sample.GetLazyValue(depth*7);

                if (depth > scene.MaxPathDepth)
                {
                    float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                    if (prob >= Sample.GetLazyValue(depth * 8))
                    {
                        Throughput /= prob;
                        pathWeight *= prob;
                    }
                    else
                    {
                        if (tracedShadowRayCount > 0)
                            PathState = PathTracerPathState.ShadowRaysOnly;
                        else
                        {
                            Splat(consumer);
                        }

                        return;
                    }
                }

                PathRay.Org = hitPoint;
                PathRay.Dir = wi.Normalize();
                PathState = PathTracerPathState.NextVertex;

#if VERBOSE
            }
            catch (Exception ex)
            {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #16
0
        public override void InitPath(IPathProcessor buffer)
        {
            base.InitPath(buffer);
            this.scene = pathIntegrator.Scene;
            this.Radiance = new RgbSpectrum(0f);
            this.Throughput = new RgbSpectrum(1f);
            this.PathState = PathTracerPathState.EyeVertex;
            this.secRays = new ShadowRayInfo[scene.ShadowRayCount];
            this.sampler = (MCMCSampler)pathIntegrator.Sampler;
            switch (this.SamplerState)
            {
                case MCMCSamplerState.LargeStep:
                case MCMCSamplerState.Initialized:
                    time = 0;
                    this.mutationsCount = 0;
                    this.rejectCount = 0;
                    //this.sampleCache.Clear();
                    this.Sample = pathIntegrator.Sampler.GetSample(null);
                    break;
                case MCMCSamplerState.SmallStep:
                    {
                        //if (rejectCount > 0)
                        //{
                        //    Print("Rejects : " + rejectCount);
                        //}
                        this.time++;
                        this.Sample = this.sampler.SmallStep(this.Sample); ;
                    }
                    break;
            }

            IRay ray;
            pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out ray);
            this.PathRay = (RayData)ray;
            this.RayIndex = -1;
            this.pathWeight = 1.0f;

            this.tracedShadowRayCount = 0;
            this.depth = 0;
            this.specularBounce = true;
        }
예제 #17
0
        public override sealed void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
            int currentTriangleIndex = 0;
#if VERBOSE

            try {
#endif

            if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                (tracedShadowRayCount > 0))
            {
                var continueRays = new List<ShadowRayInfo>();
                for (int i = 0; i < tracedShadowRayCount; ++i)
                {
                    RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].ShadowRayIndex];
                    RgbSpectrum attenuation;
                    bool continueTrace;
                    if (this.ShadowRayTest(ref shadowRayHit, ref secRays[i].ShadowRay, out attenuation, out continueTrace))
                    {
                        //Radiance += attenuation * ((secRays[i].Throughput) / secRays[i].Pdf);
                        waveRadiance += secRays[i].Throughput[0]/secRays[i].Pdf;
                        //pathWeight *= secRays[i].Pdf;
                    }

                    if (continueTrace)
                    {
                        continueRays.Add(secRays[i]);
                    }
                }

                if (PathState == PathTracerPathState.ShadowRaysOnly)
                {
                    Splat(consumer);
                    return;
                }

                Array.Copy(continueRays.ToArray(), secRays, continueRays.Count);
                tracedShadowRayCount = continueRays.Count;
            }
            RayHit rayHit = rayBuffer.rayHits[RayIndex];
            Vector wo = -PathRay.Dir;

            depth++;
            bool missed = rayHit.Index == 0xffffffffu;
            if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
            {
                if (missed)
                {
                    //Radiance += this.scene.SampleEnvironment(ref wo) * Throughput;
                    //var sampledEnvironment = this.scene.SampleEnvironment(ref wo); //!
                    waveRadiance += wlSampler.SampleEnvironment(HeroWavelength, ref wo);
                    //Radiance.MAdd(ref sampledEnvironment, ref Throughput);
                }
                Splat(consumer);

                return;
            }

            //var mesh = scene.GetMeshByTriangleIndex(currentTriangleIndex);
            //rayHit.Index += (uint)mesh.StartTriangle;
            // Something was hit
            if (hitInfo == null)
            {
                hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit);
            }
            else
            {
                SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo);
            }
            currentTriangleIndex = (int)rayHit.Index;

            if (hitInfo == null)
            {
                System.Diagnostics.Debugger.Break();
            }
            //If Hit light)

            if (hitInfo.IsLight)
            {
                if (specularBounce || depth == 1)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);

                    if (lt != null)
                    {
                        waveRadiance += wlSampler.SampleLight(lt, HeroWavelength);
                        //var le = hitInfo.Color * (RgbSpectrum)(lt.Le(ref wo)); //!
                        //Radiance += Throughput * le;
                        //Radiance.MAdd(ref Throughput, ref le);
                    }
                }
                Splat(consumer);

                return;
            }

            var hitPoint = PathRay.Point(rayHit.Distance);

            tracedShadowRayCount = 0;
            var bsdf = wlSampler.GetBrdf(scene.GetMeshByTriangleIndex(currentTriangleIndex).MaterialID);

            //if (!hitInfo.TextureData.Alpha.IsBlack())
            //{
            //    Throughput *= (RgbSpectrum.UnitSpectrum() - hitInfo.TextureData.Alpha);
            //    PathRay = new RayData(hitPoint, -wo);
            //    return;
            //}

            if (bsdf.IsDiffuse())
            {
                float lightStrategyPdf = LightSampler.StrategyPdf;
                //scene.ShadowRaysPerSample/(float)scene.Lights.Length;
                //RgbSpectrum lightTroughtput = Throughput * hitInfo.Color;
                float ltThroughput = waveThroughput*bsdf.Kd.Sample(HeroWavelength);
                LightSampler.EvaluateShadow(ref hitPoint, ref hitInfo.Normal, Sample.GetLazyValue(depth),
                                            Sample.GetLazyValue(2*depth+1), Sample.GetLazyValue(3*depth+2), ref ls);
                for (int index = 0; index < ls.Length; index++)
                {

                    if (ls[index].Pdf <= 0f)
                        continue;
                    ls[index].Lambda = wlSampler.SampleLight(scene.Lights[ls[index].LightIndex], HeroWavelength);
                    secRays[tracedShadowRayCount].Throughput[0] = ls[index].Lambda;
                    secRays[tracedShadowRayCount].Pdf = ls[index].Pdf;
                    secRays[tracedShadowRayCount].ShadowRay = ls[index].LightRay;
                    Vector lwi = secRays[tracedShadowRayCount].ShadowRay.Dir;
                    float fs;
                    bsdf.F(ref secRays[tracedShadowRayCount].ShadowRay.Dir, ref wo, ref hitInfo.ShadingNormal, HeroWavelength, out fs);
                    secRays[tracedShadowRayCount].Throughput[0] *= ltThroughput*
                                                                Vector.AbsDot(ref hitInfo.Normal, ref lwi) *
                                                                fs;
                    if (secRays[tracedShadowRayCount].Throughput[0] > 0f)
                    {
#if DEBUG
                                    RayDen.Library.Core.Components.Assert.IsNotNaN(secRays[tracedShadowRayCount].Pdf);
#endif
                        secRays[tracedShadowRayCount].Pdf /= lightStrategyPdf;
                        tracedShadowRayCount++;
                    }
                }
            }

            float fPdf = 0f;
            var wi = new Vector();
            float f;
            BsdfSampleData bsdfSample;
            bsdf.Sample_f(ref wo, ref hitInfo.Normal, ref hitInfo.ShadingNormal, HeroWavelength, ref hitInfo.TextureData,
                                Sample.GetLazyValue(4 * depth + 3), Sample.GetLazyValue(5 * depth + 4), Sample.GetLazyValue(6 * depth + 5)
                                , out bsdfSample);
            f = bsdfSample.Lambda;
            fPdf = bsdfSample.Pdf;
            wi = bsdfSample.Wi;
            specularBounce = bsdfSample.SpecularBounce;

            if ((fPdf <= 0.0f))// || f.IsBlack()
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);

                }
                return;
            }
            waveThroughput *= f/fPdf;
            pathWeight *= fPdf;
            //Throughput *= (f * hitInfo.Color) / fPdf;

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(waveThroughput, scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue(7 * depth + 5))
                {
                    //Throughput /= prob;
                    waveThroughput /= prob;
                    pathWeight *= prob;
                }
                else
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;

#if VERBOSE
            }
            catch (Exception ex) {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #18
0
        public override void Advance(Core.Types.RayBuffer rayBuffer, Core.Types.SampleBuffer consumer)
        {
            int currentTriangleIndex = 0;
#if VERBOSE

            try {
#endif

            if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                (tracedShadowRayCount > 0))
            {
                for (int i = 0; i < tracedShadowRayCount; ++i)
                {
                    RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].ShadowRayIndex];
                    RgbSpectrum attenuation;
                    bool continueTrace;
                    if (this.ShadowRayTest(ref shadowRayHit, ref secRays[i].ShadowRay, out attenuation, out continueTrace))
                    {
                        float weight = 1f;//tracedShadowRayCount;
                        //                            Radiance.MADD()
                        Radiance += attenuation * (secRays[i].Throughput /(weight*secRays[i].Pdf))*100f;
                        pathWeight *= secRays[i].Pdf;
                    }
                }

                if (PathState == PathTracerPathState.ShadowRaysOnly)
                {
                    Splat(consumer);
                    return;
                }
                tracedShadowRayCount = 0;
            }
            RayHit eyeRayHit = rayBuffer.rayHits[RayIndex];
            Vector wo = -PathRay.Dir;

            depth++;
            bool eyeMissed = eyeRayHit.Index == 0xffffffffu;
            if (eyeMissed && lightDepth > 0 && tracedShadowRayCount > 0)
            {
                Console.WriteLine("!");
                
            }

            if (eyeMissed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
            {
                if (eyeMissed)
                {
                    Radiance += this.scene.SampleEnvironment(ref wo) * Throughput;
                }
                Splat(consumer);

                return;
            }

            // Something was hit
            if (hitInfo == null)
            {
                hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref eyeRayHit);
            }
            else
            {
                SurfaceSampler.GetIntersection(ref PathRay, ref eyeRayHit, ref hitInfo);
            }
            currentTriangleIndex = (int)eyeRayHit.Index;

            if (hitInfo == null)
            {
                Debugger.Break();
            }
            //If Hit light)

            if (hitInfo.IsLight)
            {
                if (specularBounce || depth == 1)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);
                    if (lt != null)
                    {
#if !NOIMPLICIT
                        var le = (RgbSpectrumInfo)(lt.Le(ref wo));
                        Radiance += Throughput * (RgbSpectrum)le;
#endif
                    }
                }
                Splat(consumer);
                return;
            }

            if (!lightStoped)
            {
                RayHit lightRayHit = rayBuffer.rayHits[LightRayIndex];
                if (lightRayHit.Miss())
                {
                    this.RestartLight();
                }
                else
                {
                    lightDepth++;
                    if (lightHitInfo == null)
                    {
                        lightHitInfo = SurfaceSampler.GetIntersection(ref LightRay, ref lightRayHit,
                                                                      IntersectionOptions.ResolveSurfaceComplete |
                                                                      IntersectionOptions.ResumeOnLight);
                    }
                    else
                    {
                        SurfaceSampler.GetIntersection(ref LightRay, ref lightRayHit, ref lightHitInfo,
                                                                      IntersectionOptions.ResolveSurfaceComplete |
                                                                      IntersectionOptions.ResumeOnLight);
                    }

                    float lPdf = 0f;
                    var lwi = new Vector();
                    var lhp = LightRay.Point(lightRayHit.Distance);
                    var lf = lightHitInfo.MMaterial.Sample_f(ref wo, out lwi, ref hitInfo.Normal,
                                                             ref hitInfo.ShadingNormal, ref Throughput,
                                                             Sample.GetLazyValue(), Sample.GetLazyValue(),
                                                             Sample.GetLazyValue(), ref hitInfo.TextureData,
                                                             out lPdf, out specularBounce);
                    var scatteringCorrection = Vector.AbsDot(ref wo, ref hitInfo.Normal) /
                                                    Vector.AbsDot(ref wo, ref hitInfo.ShadingNormal);
                    scatteringCorrection *=  Vector.AbsDot(ref lwi, ref hitInfo.ShadingNormal);
                    if (lPdf <= 0f || lf.IsBlack())
                    {
                        this.RestartLight();
                        goto eyeCont;
                    }
                    if (lightDepth 
#if DIRECT_EXPLICIT
                        > 1)
#else
                        > 0)
#endif

                    {

                        float da = (currentLightVertex > 0 ? this.lightVertices[currentLightVertex - 1].dAWeight : 1.0f)*lightWeight;

                        this.lightVertices[currentLightVertex] = new LightVertex()
                            {
                                HitPoint = lhp,
                                Normal = lightHitInfo.ShadingNormal,
                                BsdfWeight = lPdf,
                                BsdfSample = lf*scatteringCorrection,
                                dAWeight = da*(currentLightVertex > 0 
                                            ?
                                                lPdf*Geometry.G(ref lhp, ref lightVertices[currentLightVertex-1].HitPoint,ref hitInfo.ShadingNormal,ref lightVertices[currentLightVertex-1].Normal)
                                            : lPdf)*scatteringCorrection,
                                Throughput = LightThroughtput,
                                Wi = LightRay.Dir,
                            };
                        currentLightVertex++;
                    }
                    
                    LightThroughtput *= (lf / lPdf)*scatteringCorrection;
                    LightRay = new RayData(ref lhp, ref lwi);
                }
                lightStoped = currentLightVertex > scene.MaxPathDepth || LightThroughtput.IsBlack();
            }

            //if (currentLightVertex > 3)
            //{
            //    Debugger.Break();
            //}
        eyeCont:
            var hitPoint = PathRay.Point(eyeRayHit.Distance);

            tracedShadowRayCount = 0;
            var bsdf = hitInfo.MMaterial;

            if (bsdf.IsDiffuse())
            {
#if DIRECT_EXPLICIT
                float lightStrategyPdf = LightSampler.StrategyPdf;
                //scene.ShadowRaysPerSample/(float)scene.Lights.Length;
                RgbSpectrum lightTroughtput = Throughput * hitInfo.Color;
                LightSampler.EvaluateShadow(ref hitPoint, ref hitInfo.Normal, Sample.GetLazyValue(),
                                            Sample.GetLazyValue(), Sample.GetLazyValue(), ref ls);
                for (int index = 0; index < ls.Length; index++)
                {

                    if (ls[index].Pdf <= 0f)
                        continue;
                    secRays[tracedShadowRayCount].Throughput = (RgbSpectrum)(RgbSpectrumInfo)(ls[index].Spectrum);
                    secRays[tracedShadowRayCount].Pdf = ls[index].Pdf;
                    secRays[tracedShadowRayCount].ShadowRay = ls[index].LightRay;
                    Vector lwi = secRays[tracedShadowRayCount].ShadowRay.Dir;
                    RgbSpectrum fs;
                    hitInfo.MMaterial.f(ref secRays[tracedShadowRayCount].ShadowRay.Dir, ref wo, ref hitInfo.ShadingNormal, ref lightTroughtput, out fs, BrdfType.Diffuse);
                    secRays[tracedShadowRayCount].Throughput *= lightTroughtput *
                                                                Vector.AbsDot(ref hitInfo.Normal, ref lwi) *
                                                                fs;
                    if (!secRays[tracedShadowRayCount].Throughput.IsBlack())
                    {
                        secRays[tracedShadowRayCount].Pdf /= lightStrategyPdf;
                        tracedShadowRayCount++;
                    }
                }
#endif
                for (int index = 0; index < currentLightVertex; index++)
                {
                    if (lightVertices[index].Throughput.IsBlack())
                        continue;

                    var lwi = lightVertices[index].Wi;
                    RgbSpectrum fs;
                    hitInfo.MMaterial.f(ref lwi, ref wo, ref hitInfo.ShadingNormal, ref Throughput, out fs, types: BrdfType.Diffuse);
                    var dir = lightVertices[index].HitPoint - hitPoint;
                    var dirLength = dir.Length;
                    dir.NormalizeSelf();

                    secRays[tracedShadowRayCount].Throughput = Throughput*lightVertices[index].Throughput
                                                               *fs
                                                               *lightVertices[index].BsdfSample
                                                               //* Vector.AbsDot(ref hitInfo.Normal, ref lwi) 
                                                               *Geometry.G(ref hitPoint, ref lightVertices[index].HitPoint,ref hitInfo.Normal,ref lightVertices[index].Normal);

                    secRays[tracedShadowRayCount].Pdf = (pathWeight*lightVertices[index].dAWeight)
                        ;
                    //    * Geometry.G(ref hitPoint, ref lightVertices[index].HitPoint, ref hitInfo.Normal, ref lightVertices[index].Normal);
                        //1f/(depth+index) * (pathWeight*lightVertices[index].dAWeight);
                    secRays[tracedShadowRayCount].ShadowRay = new RayData(ref hitPoint, ref dir, 1e-4f, dirLength-1e-4f);
                    tracedShadowRayCount++;
                }
            }

            float fPdf = 0f;
            var wi = new Vector();
            RgbSpectrum f;

            f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                                Sample.GetLazyValue(), Sample.GetLazyValue(),
                                Sample.GetLazyValue(), ref hitInfo.TextureData,
                                out fPdf, out specularBounce);

            if ((fPdf <= 0.0f) || f.IsBlack())
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);

                }
                return;
            }
            pathWeight *= fPdf;
            Throughput *= (f) / fPdf;

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue())
                {
                    Throughput /= prob;
                    pathWeight *= prob;
                }
                else
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;

#if VERBOSE
            }
            catch (Exception ex) {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #19
0
        public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
            int currentTriangleIndex = 0;
#if VERBOSE

            try {
#endif


            if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
               (tracedShadowRayCount > 0))
            {
                for (int i = 0; i < tracedShadowRayCount; ++i)
                {
                    RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].ShadowRayIndex];
                    RgbSpectrum attenuation;
                    bool continueTrace;
                    if (this.ShadowRayTest(ref shadowRayHit, ref secRays[i].ShadowRay, out attenuation, out continueTrace))
                    {
                        Radiance += ((secRays[i].Throughput) / secRays[i].Pdf);
                    }
                }

                if (PathState == PathTracerPathState.ShadowRaysOnly)
                {
                    Splat(consumer);
                    return;
                }
                tracedShadowRayCount = 0;
            }
            var rayHit = rayBuffer.rayHits[RayIndex];
            var wo = -PathRay.Dir;

            depth++;
            var missed = rayHit.Index == 0xffffffffu;

            if (missed || depth > scene.MaxPathDepth)
            {
                if (specularBounce && missed)
                {
                    Radiance += this.scene.SampleEnvironment(ref wo) * Throughput;
                }
                Splat(consumer);

                return;
            }

            // Something was hit
            if (hitInfo == null)
            {
                hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit);
            }
            else
            {
                SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo);
            }
            currentTriangleIndex = (int)rayHit.Index;

            //If Hit light)
            if (hitInfo.IsLight)
            {
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);
                    if (lt != null)
                    {
                        var le = (RgbSpectrum)(RgbSpectrumInfo)(lt.Le(ref PathRay.Dir));
                        Radiance += Throughput * le;
                    }
                }
                Splat(consumer);

                return;
            }

            var hitPoint = PathRay.Point(rayHit.Distance);
            tracedShadowRayCount = 0;

            if (hitInfo.MMaterial.IsDiffuse())
            {
                float lightStrategyPdf = LightSampler.StrategyPdf;
                //scene.ShadowRaysPerSample/(float)scene.Lights.Length;
                RgbSpectrum lightTroughtput = Throughput * hitInfo.Color;
                LightSampler.EvaluateShadow(ref hitPoint, ref hitInfo.Normal, Sample.GetLazyValue(),
                                            Sample.GetLazyValue(), Sample.GetLazyValue(), ref ls);
                for (int index = 0; index < ls.Length; index++)
                {

                    if (ls[index].Pdf <= 0f || float.IsNaN(ls[index].Pdf))
                        continue;
                    secRays[tracedShadowRayCount].Throughput = ls[index].Spectrum.GetType() == typeof(RgbSpectrumInfo) ? (RgbSpectrum)(RgbSpectrumInfo)ls[index].Spectrum : (RgbSpectrum)ls[index].Spectrum;
                    secRays[tracedShadowRayCount].Pdf = ls[index].Pdf;
                    secRays[tracedShadowRayCount].ShadowRay = ls[index].LightRay;
                    Vector lwi = secRays[tracedShadowRayCount].ShadowRay.Dir;
                    RgbSpectrum fs;
                    hitInfo.MMaterial.f(ref secRays[tracedShadowRayCount].ShadowRay.Dir, ref wo, ref hitInfo.ShadingNormal, ref Throughput, out fs, types: BrdfType.Diffuse);
                    secRays[tracedShadowRayCount].Throughput *= lightTroughtput *
                                                                Vector.AbsDot(ref hitInfo.Normal, ref lwi) *
                                                                fs;
                    if (!secRays[tracedShadowRayCount].Throughput.IsBlack())
                    {
#if DEBUG
                        RayDen.Library.Core.Components.Assert.IsNotNaN(secRays[tracedShadowRayCount].Pdf);
#endif
                        secRays[tracedShadowRayCount].Pdf /= lightStrategyPdf * scene.ShadowRayCount;
                        tracedShadowRayCount++;
                    }
                }
            }



            float fPdf;
            Vector wi;

            var f = hitInfo.MMaterial.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                                                      Sample.GetLazyValue(), Sample.GetLazyValue(),
                                                      Sample.GetLazyValue(), ref hitInfo.TextureData,
                                                      out fPdf, out specularBounce);

            if ((fPdf <= 0.0f) || f.IsBlack())
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);

                }
                return;
            }
            pathWeight *= fPdf;
            Throughput *= (f * hitInfo.Color) / fPdf;

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue())
                {
                    Throughput /= prob;
                    pathWeight *= prob;
                }
                else
                {

                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;

#if VERBOSE
            }
            catch (Exception ex) {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #20
0
        public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
            int currentTriangleIndex = 0;
#if VERBOSE

            try
            {
#endif
                var misWeight = 1.0f;

                base.Advance(rayBuffer, consumer);

                RayHit rayHit = rayBuffer.rayHits[RayIndex];

                if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                    (tracedShadowRayCount > 0))
                {
                    for (int i = 0; i < tracedShadowRayCount; ++i)
                    {
                        RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].currentShadowRayIndex];
                        RgbSpectrumInfo attenuation;
                        if (this.ShadowRayTest(ref shadowRayHit, out attenuation))
                        {
                            //                            Radiance.MADD()
                            Radiance += (RgbSpectrum)(attenuation * ((secRays[i].color)));
                            pathWeight *= secRays[i].pdf;
                        }
                    }
                    tracedShadowRayCount = 0;
                    if (PathState == PathTracerPathState.ShadowRaysOnly)
                    {
                        Splat(consumer);
                        return;
                    }
                }

                depth++;
                bool missed = rayHit.Index == 0xffffffffu;
                Vector wo = -PathRay.Dir;

                if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
                {
                    if (depth > 0 && !specularBounce)
                    {
                        misWeight = Mis2(lastPdfW, 1f / MathLab.INVPI);
                    }

                    if (specularBounce)
                    {
                        Radiance += this.SampleEnvironment(wo) * Throughput * misWeight;
                    }

                    Splat(consumer);



                    return;
                }

                // Something was hit
                if (hitInfo == null)
                {
                    hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit);
                }
                else
                {
                    SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo);
                }
                currentTriangleIndex = (int)rayHit.Index;

                if (hitInfo == null)
                {
                    Debugger.Break();
                }
                //If Hit light)
                if (hitInfo.IsLight)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);

                    if (lt !=null)
                   {
                        float wpdf;
                        var l =(RgbSpectrum)lt.Emittance(ref wo, out wpdf)*Throughput;
                        if (!specularBounce & depth > 0)
                        {
                            var dpdf = MathLab.PdfAtoW(wpdf, rayHit.Distance, Vector.AbsDot(ref wo, ref hitInfo.Normal));
                            var lightPickProb = 1.0f/scene.Lights.Length;
                            misWeight = Mis2(lastPdfW, dpdf*lightPickProb);
                        }

                        Radiance += Throughput*l*misWeight;
                    }
                    else
                    {
                        float pdf;
                        var le = hitInfo.Color * lt.Emittance(ref wo, out pdf);
                        //Radiance += Throughput * le;

                        Radiance.MAdd(ref Throughput, ref le);
                    }
                    Splat(consumer);

                    return;
                }

                var hitPoint = PathRay.Point(rayHit.Distance);

                tracedShadowRayCount = 0;
                var bsdf = hitInfo.MMaterial;
                float contProb = bsdf.ContinuationProbability;

                if (bsdf.IsDiffuse())
                {
                    float lightStrategyPdf = scene.ShadowRayCount / (float)scene.Lights.Length;
                    RgbSpectrum lightTroughtput = Throughput * hitInfo.Color;
                    for (int i = 0; i < scene.ShadowRayCount; ++i)
                    {
                        int currentLightIndex = scene.SampleLights(Sample.GetLazyValue());
                        var light = scene.Lights[currentLightIndex];
                        int tries = RejectionSamplingMaxLighTries;
                    light_restart:
                        light.EvaluateShadow(ref hitPoint, ref hitInfo.ShadingNormal, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), ref ls);
                        if (ls.Pdf <= 0f)
                        {
                            tries--;
                            if (tries == 0)
                                continue;
                            goto light_restart;
                        }
                        RgbSpectrum f_s;
                        bsdf.f(ref secRays[tracedShadowRayCount].shadowRay.Dir, ref wo, ref hitInfo.ShadingNormal, ref Throughput, out f_s);

                        if (f_s.IsBlack())
                        {
                            continue;
                        }
                        var fs = (RgbSpectrumInfo) f_s;
                        var bsdfPdfW = bsdf.Pdf(ref secRays[tracedShadowRayCount].shadowRay.Dir, ref wo);

                        float weight = 1f;


                        secRays[tracedShadowRayCount].color = (RgbSpectrumInfo)(RgbSpectrum)(ls.Spectrum);
                        secRays[tracedShadowRayCount].pdf = ls.Pdf;
                        secRays[tracedShadowRayCount].shadowRay = ls.LightRay;
                        Vector lwi = -secRays[tracedShadowRayCount].shadowRay.Dir;
                        var lightPdf = ls.Pdf * lightStrategyPdf;

                        if (!light.IsDelta)
                        {
                            bsdfPdfW *= contProb;
                            weight = Mis2(lightPdf, bsdfPdfW);
                            secRays[tracedShadowRayCount].pdf = 1f;
                            secRays[tracedShadowRayCount].color = (weight * Vector.AbsDot(ref hitInfo.ShadingNormal, ref lwi) / (lightPdf)) * (lightTroughtput * fs);
                        }
                        else
                        {
                            secRays[tracedShadowRayCount].color *= (lightTroughtput *
                                                                   Vector.AbsDot(ref hitInfo.ShadingNormal, ref lwi) *
                                                                   fs);
                            secRays[tracedShadowRayCount].color /= lightPdf;
                        }
                        if (!secRays[tracedShadowRayCount].color.IsBlack())
                        {
                            tracedShadowRayCount++;
                        }
                    }
                }

                float fPdf;
                Vector wi;
                int btries = RejectionSamplingMaxBsdfTries;

            bsdf_restart:
                RgbSpectrum f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                                                          Sample.GetLazyValue(), Sample.GetLazyValue(),
                                                          Sample.GetLazyValue(), ref hitInfo.TextureData,
                                                          out fPdf, out specularBounce)*hitInfo.Color;

                if ((fPdf <= 0.0f) || f.IsBlack())
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        btries--;
                        if (btries == 0)
                        {
                            Splat(consumer);

                        }
                        else
                        {
                            goto bsdf_restart;
                        }
                    }
                    return;
                }
                pathWeight *= fPdf;
                Throughput *= (f*hitInfo.Color) / fPdf;
                lastPdfW = fPdf * contProb;
                if (depth > scene.MaxPathDepth)
                {
                    float prob = Math.Max(contProb, scene.RussianRuletteImportanceCap);
                    if (prob >= Sample.GetLazyValue())
                    {
                        Throughput /= prob;
                        pathWeight *= prob;
                    }
                    else
                    {
                        if (tracedShadowRayCount > 0)
                            PathState = PathTracerPathState.ShadowRaysOnly;
                        else
                        {
                            Splat(consumer);

                        }

                        return;
                    }
                }

                PathRay.Org = hitPoint;
                PathRay.Dir = wi.Normalize();
                PathState = PathTracerPathState.NextVertex;

#if VERBOSE
            }
            catch (Exception ex)
            {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #21
0
        public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
#if VERBOSE
            try
            {
#endif
                base.Advance(rayBuffer, consumer);



                var rayHit = new RayHit();

                Vector wo = -PathRay.Dir;

                switch (PathState)
                {
                    case PathTracerPathState.EyeVertex:
                        float t, t1;
                        if (scene.VolumeIntegrator != null && scene.VolumeIntegrator.GetBounds().Intersect(PathRay, out t, out t1))
                        {
                            rayHit = rayBuffer.rayHits[RayIndex];

                            // Use Russian Roulette to check if I have to do participating media computation or not
                            if (Sample.GetLazyValue() <= scene.VolumeIntegrator.GetRRProbability())
                            {
                                RayData volumeRay = new RayData(ref PathRay.Org, ref PathRay.Dir, 0f,
                                                                rayHit.Miss() ? 1e10f : rayHit.Distance);
                                scene.VolumeIntegrator.GenerateLiRays(scene, Sample, ref volumeRay, volumeComp);
                                Radiance += volumeComp.GetEmittedLight();

                                if (volumeComp.GetRayCount() > 0)
                                {
                                    // Do the EYE_VERTEX_VOLUME_STEP
                                    PathState = PathTracerPathState.EyeVolume;
                                    eyeHit = (rayBuffer.rayHits[RayIndex]);
                                    return;
                                }
                            }
                        }
                        else
                        {
                            rayHit = rayBuffer.rayHits[RayIndex];
                        }
                        break;
                    case PathTracerPathState.NextVertex:
                        rayHit = rayBuffer.rayHits[RayIndex];
                        break;
                    case PathTracerPathState.EyeVolume:
                        Radiance += Throughput * volumeComp.CollectResults(rayBuffer) /
                                    scene.VolumeIntegrator.GetRRProbability();
                        rayHit = eyeHit;
                        break;
                }

                if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                    (tracedShadowRayCount > 0))
                {
                    for (int i = 0; i < tracedShadowRayCount; ++i)
                    {
                        RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].currentShadowRayIndex];
                        RgbSpectrum attenuation;
                        if (this.ShadowRayTest(ref shadowRayHit, out attenuation))
                        {
                            //                            Radiance.MADD()
                            Radiance += attenuation * ((secRays[i].color) / secRays[i].pdf);
                            pathWeight *= secRays[i].pdf;
                        }
                    }
                    tracedShadowRayCount = 0;
                    if (PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
                    {
                        Splat(consumer);
                        return;
                    }
                }

                depth++;
                bool missed = rayHit.Index == 0xffffffffu;
                if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
                {
                    if (specularBounce && missed)
                    {
                        Radiance += this.SampleEnvironment(-PathRay.Dir) * Throughput;
                    }
                    Splat(consumer);
                    return;
                }

                // Something was hit
                if (_hitInfo == null)
                    _hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit);
                else
                {
                    SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref _hitInfo);
                }
                var currentTriangleIndex = (int)rayHit.Index;

                //If Hit light)
                if (_hitInfo.IsLight)
                {
                    if (specularBounce)
                    {
                        var lt = scene.GetLightByIndex(currentTriangleIndex);
                        if (lt == null)
                        {
                            goto errro;
                        }
                        var le = (RgbSpectrum)(RgbSpectrumInfo)(lt.Le(ref wo));
                        Radiance += Throughput * le;
                    }
                    Splat(consumer);
                    return;
                }
            @errro:

                var hitPoint = PathRay.Point(rayHit.Distance);

                tracedShadowRayCount = 0;
                if (_hitInfo.MMaterial.IsDiffuse())
                {
                    float lightStrategyPdf = scene.ShadowRayCount / (float)scene.Lights.Length;
                    RgbSpectrum lightTroughtput = Throughput * _hitInfo.Color;
                    for (int i = 0; i < scene.ShadowRaysPerSample; ++i)
                    {
                        int currentLightIndex = scene.SampleLights(Sample.GetLazyValue());
                        var light = scene.Lights[currentLightIndex];

                        var ls = new LightSample();
                        light.EvaluateShadow(ref hitPoint, ref _hitInfo.ShadingNormal, Sample.GetLazyValue(),
                                             Sample.GetLazyValue(), Sample.GetLazyValue(), ref ls);
                        if (ls.Pdf <= 0f)
                        {
                            continue;
                        }

                        secRays[tracedShadowRayCount].color = ls.Spectrum.GetType() == typeof(RgbSpectrumInfo) ? (RgbSpectrum)(RgbSpectrumInfo)ls.Spectrum : (RgbSpectrum)ls.Spectrum;
                        secRays[tracedShadowRayCount].pdf = ls.Pdf;
                        secRays[tracedShadowRayCount].shadowRay = ls.LightRay;

                        RgbSpectrum fs;
                        _hitInfo.MMaterial.f(
                            ref secRays[tracedShadowRayCount].shadowRay.Dir,
                            ref wo, ref _hitInfo.ShadingNormal, ref Throughput, out fs);
                        Vector lwi = secRays[tracedShadowRayCount].shadowRay.Dir;
                        secRays[tracedShadowRayCount].color *= lightTroughtput *
                                                               Vector.AbsDot(ref _hitInfo.ShadingNormal, ref lwi) *
                                                               fs;
                        if (!secRays[tracedShadowRayCount].color.IsBlack())
                        {
                            secRays[tracedShadowRayCount].pdf *= lightStrategyPdf;
                            tracedShadowRayCount++;
                        }
                    }
                }

                float fPdf;
                Vector wi;

                RgbSpectrum f = _hitInfo.MMaterial.Sample_f(ref wo, out wi, ref _hitInfo.Normal, ref _hitInfo.ShadingNormal, ref Throughput,
                                                          Sample.GetLazyValue(), Sample.GetLazyValue(),
                                                          Sample.GetLazyValue(), ref _hitInfo.TextureData,
                                                          out fPdf, out specularBounce);

                if ((fPdf <= 0.0f) || f.IsBlack())
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);
                    }
                    return;
                }
                pathWeight *= fPdf;
                Throughput *= f / fPdf;

                if (depth > scene.MaxPathDepth)
                {
                    float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                    if (prob >= Sample.GetLazyValue())
                    {
                        Throughput /= prob;
                        pathWeight *= prob;
                    }
                    else
                    {
                        if (tracedShadowRayCount > 0)
                            PathState = PathTracerPathState.ShadowRaysOnly;
                        else
                        {
                            Splat(consumer);
                        }

                        return;
                    }
                }

                PathRay.Org = hitPoint;
                PathRay.Dir = wi.Normalize();
                PathState = PathTracerPathState.NextVertex;

#if VERBOSE

            }
            catch (Exception ex)
            {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);
                throw;
            }
#endif
        }
예제 #22
0
        public override sealed void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
            int currentTriangleIndex = 0;
#if VERBOSE

            try {
#endif

            if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                (tracedShadowRayCount > 0))
            {
                for (int i = 0; i < tracedShadowRayCount; ++i)
                {
                    RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].ShadowRayIndex];
                    RgbSpectrum attenuation;
                    bool continueTrace;
                    if (this.ShadowRayTest(ref shadowRayHit, ref secRays[i].ShadowRay, out attenuation, out continueTrace))
                    {
                        //                            Radiance.MADD()
                        Radiance += attenuation * ((secRays[i].Throughput) / secRays[i].Pdf);
                        pathWeight *= secRays[i].Pdf;
                    }
                }

                if (PathState == PathTracerPathState.ShadowRaysOnly)
                {
                    Splat(consumer);
                    return;
                }
                tracedShadowRayCount = 0;
            }
            RayHit rayHit = rayBuffer.rayHits[RayIndex];
            Vector wo = -PathRay.Dir;

            depth++;
            bool missed = rayHit.Index == 0xffffffffu;
            if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
            {
                if (missed)
                {
                    Radiance += this.scene.SampleEnvironment(ref wo) * Throughput;
                }
                Splat(consumer);

                return;
            }

            // Something was hit
            if (hitInfo == null)
            {
                hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit);
            }
            else
            {
                SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo);
            }
            currentTriangleIndex = (int)rayHit.Index;

            if (hitInfo == null)
            {
                Debugger.Break();
            }
            //If Hit light)

            if (hitInfo.IsLight)
            {
                if (specularBounce || depth == 1)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);
                    if (lt != null)
                    {
                        var le = (RgbSpectrum)(lt.Le(ref wo));
                        Radiance += Throughput * le;
                    }
                }
                Splat(consumer);

                return;
            }

            var hitPoint = PathRay.Point(rayHit.Distance);

            tracedShadowRayCount = 0;
            var bsdf = hitInfo.MMaterial;

            if (!hitInfo.TextureData.Alpha.IsBlack())
            {
                Throughput *= (RgbSpectrum.UnitSpectrum() - (RgbSpectrum) hitInfo.TextureData.Alpha);
                PathRay = new RayData(hitPoint, -wo);
                return;
            }

            if (bsdf.IsDiffuse())
            {
                float lightStrategyPdf = LightSampler.StrategyPdf;
                //scene.ShadowRaysPerSample/(float)scene.Lights.Length;
                RgbSpectrum lightTroughtput = Throughput * hitInfo.Color;
                int rs = 0;
            @lstart:
                LightSampler.EvaluateShadow(ref hitPoint, ref hitInfo.Normal, Sample.GetLazyValue(),
                                            Sample.GetLazyValue(), Sample.GetLazyValue(), ref ls);
                for (int index = 0; index < ls.Length; index++)
                {

                    if (ls[index].Pdf <= 0f)
                        continue;
                    secRays[tracedShadowRayCount].Throughput = (RgbSpectrum)(ls[index].Spectrum);
                    secRays[tracedShadowRayCount].Pdf = ls[index].Pdf;
                    secRays[tracedShadowRayCount].ShadowRay = ls[index].LightRay;
                    Vector lwi = secRays[tracedShadowRayCount].ShadowRay.Dir;
                    RgbSpectrum fs;
                    hitInfo.MMaterial.f(ref secRays[tracedShadowRayCount].ShadowRay.Dir, ref wo, ref hitInfo.ShadingNormal, ref Throughput, out fs, types: BrdfType.Diffuse);
                    secRays[tracedShadowRayCount].Throughput *= lightTroughtput *
                                                                Vector.AbsDot(ref hitInfo.Normal, ref lwi) *
                                                                fs;
                    if (!secRays[tracedShadowRayCount].Throughput.IsBlack())
                    {
                        secRays[tracedShadowRayCount].Pdf /= lightStrategyPdf;
                        tracedShadowRayCount++;
                    }
                }
                if (tracedShadowRayCount == 0 && rs < lightResampling)
                {
                    rs++;
                    goto @lstart;
                }

                if (rs > 0)
                {
                    for (int index = 0; index < secRays.Length; index++)
                    {
                        secRays[index].Pdf /= (1f+rs);
                    }
                }
            }

            float fPdf = 0f;
            var wi = new Vector();
            RgbSpectrum f;

            if (depth > 1)
            {

                f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                                  Sample.GetLazyValue(), Sample.GetLazyValue(),
                                  Sample.GetLazyValue(), ref hitInfo.TextureData,
                                  out fPdf, out specularBounce);
            }
            else
            {
                int samplesCount = 4;
                var bsdfData = new Tuple<Vector, float, RgbSpectrum>[samplesCount];
                var totalF = new RgbSpectrum();
                float totalPdf =0;
                for (int i = 0; i < samplesCount; i++)
                {
                    Vector Wi;
                    float pdf;
                    var Fr = bsdf.Sample_f(ref wo, out Wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                           Sample.GetLazyValue(), Sample.GetLazyValue(),
                           Sample.GetLazyValue(), ref hitInfo.TextureData,
                           out pdf, out specularBounce);
                    totalF += Fr;
                    totalPdf += pdf;

                    bsdfData[i] = new Tuple<Vector, float, RgbSpectrum>(Wi, pdf, Fr);
                }

                var bsdfSamples = bsdfData.OrderBy(i => i.Item2).ToArray();
                fPdf = bsdfSamples[0].Item2;
                wi = bsdfSamples[0].Item1;
                f = totalF/4f;
            }

            if ((fPdf <= 0.0f) || f.IsBlack())
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);

                }
                return;
            }
            pathWeight *= fPdf;
            Throughput *= (f * hitInfo.Color) / fPdf;

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue())
                {
                    Throughput /= prob;
                    pathWeight *= prob;
                }
                else
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;

#if VERBOSE
            }
            catch (Exception ex) {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #23
0
        public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer)
        {
            int currentTriangleIndex = 0;
#if VERBOSE

            try {
#endif

            base.Advance(rayBuffer, consumer);

            RayHit rayHit = rayBuffer.rayHits[RayIndex];

            if (((PathState == PathTracerPathState.ShadowRaysOnly) || (PathState == PathTracerPathState.NextVertex)) &&
                (tracedShadowRayCount > 0))
            {
                for (int i = 0; i < tracedShadowRayCount; ++i)
                {
                    RayHit shadowRayHit = rayBuffer.rayHits[secRays[i].currentShadowRayIndex];
                    RgbSpectrum attenuation;
                    bool continueTrace;
                    if (this.ShadowRayTest(ref shadowRayHit, ref secRays[i].shadowRay, out attenuation, out continueTrace))
                    {
                        //                            Radiance.MADD()
                        Radiance += ((secRays[i].color) / secRays[i].pdf);
                        pathWeight *= secRays[i].pdf;
                        var d = secRays[i].shadowRay.Point(shadowRayHit.Distance);
                        var pix = scene.Camera.UnProject(ref d);
                        this.Splat(consumer, pix.x, 720f - pix.y, ref Radiance );
                    }
                }

                if (PathState == PathTracerPathState.ShadowRaysOnly)
                {
                    Splat(consumer);
                    return;
                }
                tracedShadowRayCount = 0;

            }

            depth++;
            bool missed = rayHit.Index == 0xffffffffu;
            if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
            {
                if (missed)
                {
                    RgbSpectrum env;
                    this.SampleEnvironment(ref PathRay.Dir, out env);
                    Radiance += env * Throughput;
                }
                Splat(consumer);

                return;
            }

            // Something was hit
            if (hitInfo == null)
            {
                hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, IntersectionOptions.ResolveObject);
            }
            else
            {
                SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo, IntersectionOptions.ResolveObject);
            }
            currentTriangleIndex = (int)rayHit.Index;

            if (hitInfo == null)
            {
                Debugger.Break();
            }
            Vector wo = -PathRay.Dir;
            var hitPoint = PathRay.Point(rayHit.Distance);

            //If Hit light)
            if (hitInfo.IsLight)
            {
                //if (specularBounce || depth == 1)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);
                    if (lt != null)
                    {
                        var le = (RgbSpectrum)(lt.Le(ref wo));
                        Throughput *= le;
                        AddEyeRay(ref hitPoint, ref wo, ref Throughput, 1f);
                        PathState = PathTracerPathState.ShadowRaysOnly;
                        return;
                    }
                }
           }


            var bsdf = hitInfo.MMaterial;

            if (bsdf.IsDiffuse())
            {
                float lightStrategyPdf = 1f;
                //scene.ShadowRaysPerSample/(float)scene.Lights.Length;
                var lightTroughtput = Throughput*hitInfo.Color;

                AddEyeRay(ref hitPoint, ref wo, ref lightTroughtput, lightStrategyPdf );

           }

            float fPdf = 0f;
            var wi = new Vector();
            RgbSpectrum f;
     
            f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                                Sample.GetLazyValue(), Sample.GetLazyValue(),
                                Sample.GetLazyValue(), ref hitInfo.TextureData,
                                out fPdf, out specularBounce)*hitInfo.Color;

            if ((fPdf <= 0.0f) || f.IsBlack())
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);

                }
                return;
            }
            pathWeight *= fPdf;
            Throughput *= f / fPdf;

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue())
                {
                    Throughput /= prob;
                    pathWeight *= prob;
                }
                else
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);

                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;

#if VERBOSE
            }
            catch (Exception ex) {
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Advance path exception");
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Error triangle {0}", currentTriangleIndex);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message);
                RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace);

            }
#endif
        }
예제 #24
0
        private void AdvanceNewPath(RayBuffer rayBuffer, SampleBuffer consumer)
        {
            int currentTriangleIndex;
            RayHit rayHit = rayBuffer.rayHits[RayIndex];
            Vector wo = -PathRay.Dir;
            PathVertex vertex = null;
            if (Vertices[depth] == null)
            {
                vertex = new PathVertex();
                Vertices[depth] = vertex;
            }
            else
            {
                vertex = Vertices[depth];
            }
            depth++;
            bool missed = rayHit.Index == 0xffffffffu;
            if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth)
            {
                if (missed)
                {
                    //Radiance += this.scene.SampleEnvironment(ref wo) * Throughput;
                    var sampledEnvironment = this.scene.SampleEnvironment(ref wo);
                    Radiance.MAdd(ref sampledEnvironment, ref Throughput);
                    if (scene.EnvironmentMap != null)
                    {
                        mutate = true;
                    }
                }
                Splat(consumer);

                return;
            }

            //var mesh = scene.GetMeshByTriangleIndex(currentTriangleIndex);
            //rayHit.Index += (uint)mesh.StartTriangle;
            // Something was hit
            var bsdf = EvalIntersection(ref rayHit);
            currentTriangleIndex = (int)rayHit.Index;
            vertex.Bsdf = bsdf;
            vertex.TriangleIndex = currentTriangleIndex;

            if (hitInfo == null)
            {
                Debugger.Break();
            }
            //If Hit light)

            if (hitInfo.IsLight)
            {
                //if (bsdfEvent.Has(BsdfEvent.Specular) || depth == 1)
                {
                    var lt = scene.GetLightByIndex(currentTriangleIndex);
                    if (lt != null)
                    {
                        float pdf;
                        var le = hitInfo.Color * lt.Emittance(ref wo, out pdf);
                        //Radiance += Throughput * le;
                        if (!le.IsBlack())
                            mutate = true;

                        Radiance.MAdd(ref Throughput, ref le);
                    }
                }
                Splat(consumer);

                return;
            }

            var hitPoint = PathRay.Point(rayHit.Distance);
            vertex.HitPoint = hitPoint;
            tracedShadowRayCount = 0;


            if (!hitInfo.TextureData.Alpha.IsBlack())
            {
                Throughput *= (RgbSpectrum.UnitSpectrum() - (RgbSpectrum)hitInfo.TextureData.Alpha);
                PathRay = new RayData(hitPoint, -wo);
                return;
            }

            float fPdf;
            Vector wi;
            RgbSpectrum f;
            hitInfo.TextureData.Throughput = Throughput;
            prevEvent = bsdfEvent;


            f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput,
                Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue()
                , ref hitInfo.TextureData, out fPdf, out bsdfEvent);

            //if (prevEvent.Has(BsdfEvent.Transmit) && bsdfEvent.Has(BsdfEvent.Transmit))
            //{
            //    Throughput *= MathLab.Exp(-rayHit.Distance) * 0.2f;
            //}
            vertex.BsdfSample = f;
            vertex.BsdfWeight = fPdf;
            vertex.Event = bsdfEvent;
            vertex.Wo = wo;
            vertex.Wi = wi;
            vertex.ShadeNormal = hitInfo.ShadingNormal;


            if ((fPdf <= 0.0f) || f.IsBlack())
            {
                if (tracedShadowRayCount > 0)
                    PathState = PathTracerPathState.ShadowRaysOnly;
                else
                {
                    Splat(consumer);
                }
                return;
            }
            Throughput *= (f * hitInfo.Color) / fPdf;
            pathDensity *= fPdf;

            if (depth > scene.MaxPathDepth)
            {
                float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap);
                if (prob >= Sample.GetLazyValue())
                {
                    Throughput /= prob;
                    pathDensity *= prob;

                }
                else
                {
                    if (tracedShadowRayCount > 0)
                        PathState = PathTracerPathState.ShadowRaysOnly;
                    else
                    {
                        Splat(consumer);
                    }

                    return;
                }
            }

            PathRay.Org = hitPoint;
            PathRay.Dir = wi.Normalize();
            PathState = PathTracerPathState.NextVertex;
        }