public bool NextVertex(ref SurfaceIntersectionData hit, ref RayData pathRay, ref RgbSpectrum throughput, int depth, out float pdf) { var currentTriangleIndex = (int)hit.Hit.Index; var lt = Scene.GetLightByIndex(currentTriangleIndex); var wo = -pathRay.Dir; pdf = 1f; if (hit.Brdf.IsSpecular() || depth == 1) { if (lt != null) { var le = hit.Color * lt.Emittance(ref wo, out pdf); throughput.MAdd(ref throughput, ref le); } } return false; }
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 }
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 }
public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer) { int currentTriangleIndex = 0; #if VERBOSE try { #endif base.Advance(rayBuffer, consumer); var rayHit = rayBuffer.rayHits[RayIndex]; depth++; var missed = rayHit.Index == 0xffffffffu; var wo = -PathRay.Dir; 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; 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()) { 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 { Splat(consumer); return; } } PathRay.Org = hitPoint; PathRay.Dir = wi.Normalize(); #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 }
public SurfaceIntersectionData GetIntersection(ref RayData PathRay, ref RayHit hit, IntersectionOptions flags) { var ii = new SurfaceIntersectionData(ref hit, false); EvalIntersectionAdvanced(ref PathRay, ref hit, ref ii, flags); return ii; }
public bool Match(ref SurfaceIntersectionData hit) { return hit.Brdf.IsDiffuse(); }
public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer) { int currentTriangleIndex = 0; #if VERBOSE try { #endif if ((State != RayTracerPathState.Eye) && (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 (State == RayTracerPathState.OnlyShadow) { Splat(consumer); return; } tracedShadowRayCount = 0; } var rayHit = rayBuffer.rayHits[RayIndex]; var wo = -PathRay.Dir; depth++; var missed = rayHit.Index == 0xffffffffu; if (missed || State == RayTracerPathState.OnlyShadow || 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; } if (hitInfo == null) { hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit); } else { SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo); } currentTriangleIndex = (int) rayHit.Index; var hitPoint = PathRay.Point(rayHit.Distance); tracedShadowRayCount = 0; var bsdf = hitInfo.MMaterial; 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++; } } } if (bsdf.IsSpecular() || bsdf.IsRefractive() && depth < scene.MaxPathDepth) { var 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) State = RayTracerPathState.OnlyShadow; else { Splat(consumer); } return; } pathWeight *= fPdf; Throughput *= (f)/fPdf; State = RayTracerPathState.Reflection; PathRay.Org = hitPoint; PathRay.Dir = wi.Normalize(); //Radiance += Throughput; } else { if (tracedShadowRayCount > 0) State = RayTracerPathState.OnlyShadow; else Splat(consumer); } #if VERBOSE } catch (Exception ex) { Tracer.TraceLine(ex.Message); throw; } #endif }
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 }
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 }
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 }
public SurfaceIntersectionData GetIntersection(ref RayData PathRay, ref RayHit hit) { var ii = new SurfaceIntersectionData(ref hit, false); EvalIntersection(ref PathRay, ref hit, ref ii); return ii; }
private void EvalIntersectionAdvanced(ref RayData PathRay, ref RayHit hit, ref SurfaceIntersectionData ii, IntersectionOptions options) { ITriangleMesh mesh = null; #if VERBOSE try { #endif var currentTriangleIndex = (int)hit.Index; bool isLight = scene.IsLight(currentTriangleIndex); ii.Hit = hit; ii.isLight = isLight; mesh = scene.GetMeshByTriangleIndex(currentTriangleIndex); if (mesh == null) //|| mesh.MeshName.Equals("COL254_01", StringComparison.InvariantCultureIgnoreCase)) { //ii.Color = new RgbSpectrum(1f); //Debugger.Break(); throw new ApplicationException("Invalid triangle index " + currentTriangleIndex + " Mesh not found"); } var meshMat = mesh.MaterialID; ii.isVolume = scene.IsVolumeTriangle(currentTriangleIndex); ii.MMaterial = scene.MatLib.GetSurfMat(meshMat); var matInfo = scene.MaterialProvider.Get(meshMat); mesh.InterpolateTriUV(currentTriangleIndex, hit.U, hit.V, out ii.TexCoords); if (ii.isVolume) { var volumeMaterialInfo = vm.GetMaterialInfo(mesh.MaterialID); vmSampler.Sample(volumeMaterialInfo, ii.Hit.Distance, ref PathRay, out ii.VolumeData); //texSampler.SampleTexture(hit.U, hit.V, volumeMaterialInfo.Density, out ii.VolumeData.Density); //this.texSampler.SampleTexture(hit.U, hit.V, new NoiseTexture() ii.VolumeData.Density); //return; } mesh.InterpolateTriangleNormal((int)hit.Index, hit.U, hit.V, ref ii.Normal); //ii.Normal = scene.Triangles[currentTriangleIndex].ComputeNormal(scene.Vertices).Normalize(); // ii.TexCoords = new UV(hit.U, hit.V); if (isLight) { if (!options.Has(IntersectionOptions.ResumeOnLight)) return; var color = scene.GetLightByIndex((int)hit.Index).Profile.Evaluate(hit.U, hit.V); ii.Color = options.Has(IntersectionOptions.ResolveSpectralDistributions) ? ColorFactory.ToRgb(ref color) : (RgbSpectrum)(RgbSpectrumInfo)color; } if (options.Has(IntersectionOptions.ResolvePartialDerivatives)) { var p1 = scene.Vertices[scene.Triangles[currentTriangleIndex].v0.VertexIndex]; var p2 = scene.Vertices[scene.Triangles[currentTriangleIndex].v1.VertexIndex]; var p3 = scene.Vertices[scene.Triangles[currentTriangleIndex].v2.VertexIndex]; var mt = scene.sceneData.GeoData.TexCoords; var uv1 = mt[scene.sceneData.Triangles[currentTriangleIndex].v0.TexCoordIndex]; var uv2 = mt[scene.sceneData.Triangles[currentTriangleIndex].v1.TexCoordIndex]; var uv3 = mt[scene.sceneData.Triangles[currentTriangleIndex].v2.TexCoordIndex]; float du1 = uv1.x - uv3.x; float du2 = uv2.x - uv3.x; float dv1 = uv1.y - uv3.y; float dv2 = uv2.y - uv3.y; Vector dp1 = Vector.Sub(ref p1, ref p3), dp2 = Vector.Sub(ref p2, ref p3); float determinant = du1 * dv2 - dv1 * du2; if (determinant.NearEqual(0f)) { // Handle zero determinant for triangle partial derivative matrix Vector e1 = p2 - p1; Vector e2 = p3 - p1; Vector.CoordinateSystem(Vector.Normalize(Vector.Cross(ref e2, ref e1)), out ii.DpDu, out ii.DpDv); } else { float invdet = 1f / determinant; ii.DpDu = (dv2 * dp1 - dv1 * dp2) * invdet; ii.DpDv = (-du2 * dp1 + du1 * dp2) * invdet; } } if (matInfo.Alpha is ConstTextureInfo) { ii.Alpha = (matInfo.Alpha as ConstTextureInfo).Color; } if (options.Has(IntersectionOptions.ResolveTextures)) { var diffuseTex = scene.Query(meshMat, TextureType.Diffuse); if (diffuseTex != null) { #if !TEXSAMP RgbSpectrumInfo cc = diffuseTex.Sample(ii.TexCoords.U, ii.TexCoords.V); #else RgbSpectrumInfo cc; texSampler.SampleTexture(ii.TexCoords.U, ii.TexCoords.V, diffuseTex, out cc); #endif ii.Color = new RgbSpectrum(cc.c1, cc.c2, cc.c3); //ii.Color = diffuseTex.Sample(ii.TexCoords.U, ii.TexCoords.V); //ii.Color = diffuseTex.Sample(hit.U, hit.V); } else { ii.Color = RgbSpectrum.Max(ref matInfo.Ks, ref matInfo.Kd); } var bump = new Vector(0f); Vector v1, v2; Normal geoNormal = ii.Normal; Vector.CoordinateSystem(ref geoNormal, out v1, out v2); var bumpTex = scene.Query(meshMat, TextureType.Bump); if (bumpTex != null) { var map = bumpTex; var dudv = map.DUDV; RgbSpectrumInfo bs; #if TEXSAMP texSampler.SampleTexture(ii.TexCoords.U, ii.TexCoords.V, bumpTex, out bs); #else bs = bumpTex.Sample(ii.TexCoords.U, ii.TexCoords.V); #endif float b0 = bs.Filter(); UV uvdu = new UV(ii.TexCoords.U + dudv.U, ii.TexCoords.V); #if TEXSAMP texSampler.SampleTexture(uvdu.U, uvdu.V, bumpTex, out bs); #else bs = bumpTex.Sample(uvdu.U, uvdu.V); #endif float bu = bs.Filter(); UV uvdv = new UV(ii.TexCoords.U, ii.TexCoords.V + dudv.V); #if TEXSAMP texSampler.SampleTexture(uvdv.U, uvdv.V, bumpTex, out bs); #else bs = bumpTex.Sample(uvdv.U, uvdv.V); #endif float bv = bs.Filter(); float scale = 1.0f; //bm->GetScale(); bump = new Vector(scale * (bu - b0), scale * (bv - b0), 1f); ii.Normal = new Normal( v1.x * bump.x + v2.x * bump.y + geoNormal.x * bump.z, v1.y * bump.x + v2.y * bump.y + geoNormal.y * bump.z, v1.z * bump.x + v2.z * bump.y + geoNormal.z * bump.z).Normalize(); } var nfScale = 2.0f; var nfIscale = 0.5f; var normTex = scene.Query(meshMat, TextureType.Normal); if (normTex != null) { RgbSpectrumInfo color; texSampler.SampleTexture(ii.TexCoords.U, ii.TexCoords.V, normTex, out color); float x = nfScale * (color.c1 - nfIscale); float y = nfScale * (color.c2 - nfIscale); float z = nfScale * (color.c3 - nfIscale); ii.Normal = new Normal( v1.x * x + v2.x * y + geoNormal.x * z, v1.y * x + v2.y * y + geoNormal.y * z, v1.z * x + v2.z * y + geoNormal.z * z).Normalize(); } RgbSpectrumInfo reflectance = matInfo.Coefficients[3]; //(RgbSpectrumInfo) matInfo.SpecularReflectance; var reflTex = scene.Query(meshMat, TextureType.Reflection); if (reflTex != null) { texSampler.SampleTexture(ii.TexCoords.U, ii.TexCoords.V, reflTex, out reflectance); } RgbSpectrumInfo alpha = null; var alphaTex = scene.Query(meshMat, TextureType.Alpha); if (alphaTex != null) { texSampler.SampleTexture(ii.TexCoords.U, ii.TexCoords.V, alphaTex, out alpha); } var zero = new RgbSpectrum(0f); if (ii.TextureData == null) { ii.TextureData = new SurfaceTextureData() { T0 = 0.5f, Transmittance = matInfo.Ks, Exponent = matInfo.Exponent, Alpha = alpha != null ? (RgbSpectrum) alpha : zero, Diffuse = ii.Color, Roughness = bump, Bump = bump, Medium = MediumInfo.Glass, Specular = (RgbSpectrum) reflectance }; } else { ii.TextureData.T0 = 0.5f; ii.TextureData.Transmittance = matInfo.Ks; ii.TextureData.Exponent = matInfo.Exponent; ii.TextureData.Alpha = alpha != null ? (RgbSpectrum) alpha : zero; ii.TextureData.Diffuse = ii.Color; ii.TextureData.Roughness = bump; ii.TextureData.Bump = bump; ii.TextureData.Medium = MediumInfo.Glass; ii.TextureData.Specular = (RgbSpectrum) reflectance; } } else { ii.Color = //matInfo.Kd; RgbSpectrum.Max(ref matInfo.Ks, ref matInfo.Kd); ii.TextureData = new SurfaceTextureData() { T0 = 0.5f, Transmittance = matInfo.Ks, Exponent = matInfo.Exponent, //Alpha = matInfo.Ka, Diffuse = matInfo.Kd, //Roughness = bump, //Bump = bump, Medium = MediumInfo.Glass, Specular = matInfo.Ks }; } /* if (mesh.MeshName.Equals("COL254_01", StringComparison.InvariantCultureIgnoreCase)) { //ii.Color = new RgbSpectrum(1f); ii.Normal = -scene.Triangles[currentTriangleIndex].ComputeNormal(scene.Vertices).Normalize(); //ii.ShadingNormal = ii.Normal; } */ ii.ShadingNormal = (Normal.Dot(ref PathRay.Dir, ref ii.Normal) > 0f) ? -ii.Normal : ii.Normal; if (options.Has(IntersectionOptions.ResolveSpectralDistributions)) { ii.Reflectance = ColorFactory.FromRgb(RgbSpectrum.Max(ref ii.Color, ref matInfo.Kd), SpectrumType.Reflectance); } //ii.ShadingNormal = ii.Normal; /* ii.Material = new DistributionBsdf(ii.Color.y(), ii.Color, new FresnelConductor(FresnelApproxEta(ref matInfo.Kd), FresnelApproxK(ref matInfo.Ks)) //new FresnelDielectric(1.5f, 1f) //new FresnelNoOP() ); new DistributionBsdf(bump.IsZero() ? ii.Color.Filter():bump.Avg(), ii.Color); * */ //new DistributionBsdf(bump.IsZero() ? ii.Color.Filter() : bump.Avg(), ii.Color); #if VERBOSE } catch (Exception ex) { RayDen.Library.Components.SystemComponents.Tracer.TraceLine("Surface sampling error"); RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.Message); RayDen.Library.Components.SystemComponents.Tracer.TraceLine(ex.StackTrace); throw; } #endif }
private void EvalIntersection(ref RayData PathRay, ref RayHit hit, ref SurfaceIntersectionData ii) { EvalIntersectionAdvanced(ref PathRay, ref hit, ref ii, IntersectionOptions.ResolveSurfaceComplete); }
public void GetIntersection(ref RayData PathRay, ref RayHit hit, ref SurfaceIntersectionData idata, IntersectionOptions flags) { EvalIntersectionAdvanced(ref PathRay, ref hit, ref idata, flags); }
public void GetIntersection(ref RayData PathRay, ref RayHit hit, ref SurfaceIntersectionData idata) { EvalIntersection(ref PathRay, ref hit, ref idata); }
protected ISurfaceMaterial EvalIntersection(ref RayHit rayHit) { if (hitInfo == null) { hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit); } else { SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo); } return hitInfo.MMaterial; }
public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer) { int currentTriangleIndex = 0; #if VERBOSE try { #endif base.Advance(rayBuffer, consumer); RayHit rayHit = rayBuffer.rayHits[RayIndex]; depth++; bool missed = rayHit.Index == 0xffffffffu; if (missed || depth > scene.MaxPathDepth) { if (missed) { vertices[currentVertex].Event = BsdfEvent.Environment; vertices[currentVertex++].ThroughtPut = this.SampleEnvironment(PathRay.Dir); } Splat(consumer); return; } 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.IsLight) { { var lt = scene.GetLightByIndex(currentTriangleIndex); //if (lt != null) { var le = (RgbSpectrum)(RgbSpectrumInfo)(lt.Le(ref PathRay.Dir)); vertices[currentVertex].Event = BsdfEvent.Light; vertices[currentVertex++].ThroughtPut = le; } } Splat(consumer); return; } var hitPoint = PathRay.Point(rayHit.Distance); vertices[currentVertex].HitPoint = hitPoint; Vector wo = -PathRay.Dir; tracedShadowRayCount = 0; float fPdf; Vector wi; BsdfEvent @evt; 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 @evt); specularBounce = evt.Has(BsdfEvent.Specular); if ((fPdf <= 0.0f) || f.IsBlack()) { if (tracedShadowRayCount > 0) PathState = PurePathTracerPathState.ShadowRaysOnly; else { vertices[currentVertex].Event = BsdfEvent.Absorb; Splat(consumer); } return; } pathWeight *= fPdf; Throughput *= (f * hitInfo.Color) / fPdf; vertices[currentVertex].HitPoint = hitPoint; vertices[currentVertex].Wi = wi; vertices[currentVertex].Wo = wo; vertices[currentVertex].ShadeNormal = hitInfo.ShadingNormal; vertices[currentVertex].TriangleIndex = currentTriangleIndex; vertices[currentVertex].Bsdf = hitInfo.MMaterial; vertices[currentVertex].Event = @evt; vertices[currentVertex].BsdfSample = f; vertices[currentVertex].BsdfWeight = fPdf; vertices[currentVertex].ThroughtPut = (f * hitInfo.Color) / fPdf; if (depth > scene.MaxPathDepth) { float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap); if (prob >= Sample.GetLazyValue()) { Throughput /= prob; vertices[currentVertex].ThroughtPut/=prob; vertices[currentVertex].RRProbability = 1f / prob; pathWeight *= prob; } else { if (tracedShadowRayCount > 0) PathState = PurePathTracerPathState.ShadowRaysOnly; else { vertices[currentVertex].Event = BsdfEvent.Absorb; Splat(consumer); } return; } } PathRay.Org = hitPoint; PathRay.Dir = wi.Normalize(); PathState = PurePathTracerPathState.NextVertex; currentVertex++; #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 }
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 }
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 }
public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer) { base.Advance(rayBuffer, consumer); if ((PathState == BDPTSamplerState.ConnectOnly || PathState == BDPTSamplerState.PropagatePath) && tracedConnectRayCount > 0) { for (int i = 0; i < tracedConnectRayCount; ++i) { RayHit shadowRayHit = rayBuffer.rayHits[connectRays[i].ConnectRayIndex]; RgbSpectrum attenuation; if (this.ShadowRayTest(ref shadowRayHit, out attenuation)) { // Radiance.MADD() Radiance += attenuation * ((connectRays[i].Radiance) / connectRays[i].Pdf); //pathWeight *= connectRays[i].pdf; } } Splat(consumer); return; } if (!lightStop) { RayHit rayHit = rayBuffer.rayHits[LightRayIndex]; lightDepth++; bool missed = rayHit.Index == 0xffffffffu; if (missed || lightDepth > MaxLightDepth) { lightStop = true; goto Eye; } // Something was hit if (hitInfo == null) { hitInfo = SurfaceSampler.GetIntersection(ref LightRay, ref rayHit); } else { SurfaceSampler.GetIntersection(ref LightRay, ref rayHit, ref hitInfo); } var hitPoint = LightRay.Point(rayHit.Distance); if (scene.IsLight((int)rayHit.Index)) { lightStop = true; goto Eye; } Vector wo = -LightRay.Dir; var bsdf = hitInfo.MMaterial; float fPdf; Vector wi; bool specularBounce; hitInfo.Color = RgbSpectrum.UnitSpectrum(); RgbSpectrum f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref LightThroughput, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), ref hitInfo.TextureData, out fPdf, out specularBounce); if (f.IsBlack() && fPdf <= 0f) { this.lightStop = true; goto Eye; } if (bsdf.IsDiffuse() && !f.IsBlack() && lightVertices < MaxLightDepth) { this.lightPath[lightVertices].HitPoint = hitPoint; this.lightPath[lightVertices].Wi = wo; this.lightPath[lightVertices].GeoNormal = hitInfo.Normal; this.lightPath[lightVertices].Throughput = LightThroughput; this.lightPath[lightVertices].Pdf = this.lightPdf; lightVertices++; } //this.lightPdf /= fPdf; this.LightThroughput *= f / fPdf; if (lightDepth > MaxLightDepth) { this.lightStop = true; goto Eye; } LightRay.Org = hitPoint; LightRay.Dir = wi.Normalize(); PathState = BDPTSamplerState.PropagatePath; } // Eye path sampling Eye: if (!eyeStop) { RayHit rayHit = rayBuffer.rayHits[RayIndex]; eyeDepth++; bool missed = rayHit.Index == 0xffffffffu; if (missed || eyeDepth > scene.MaxPathDepth) { Radiance += this.SampleEnvironment(PathRay.Dir) * EyeThroughput; 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 (hitInfo.IsLight) { //if (specularBounce) { var lt = scene.GetLightByIndex(currentTriangleIndex); if (lt != null) { var le = (RgbSpectrum)(lt.Le(ref PathRay.Dir)); Radiance += EyeThroughput * le; } } Splat(consumer); return; } var hitPoint = PathRay.Point(rayHit.Distance); Vector wo = -PathRay.Dir; var bsdf = hitInfo.MMaterial; float fPdf; Vector wi; bool specularBounce; if (bsdf.IsDiffuse()) { float lightStrategyPdf = scene.ShadowRayCount / (float)scene.Lights.Length; RgbSpectrum lightTroughtput = EyeThroughput * hitInfo.Color; for (int i = 0; i < scene.ShadowRayCount; ++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; } connectRays[tracedConnectRayCount].Radiance = (RgbSpectrum)(ls.Spectrum); connectRays[tracedConnectRayCount].Pdf = ls.Pdf; connectRays[tracedConnectRayCount].ConnectRay = ls.LightRay; connectRays[tracedConnectRayCount].Direct = true; Vector mwi = connectRays[tracedConnectRayCount].ConnectRay.Dir; Vector lwi = connectRays[tracedConnectRayCount].ConnectRay.Dir; RgbSpectrum fs; hitInfo.MMaterial.f( ref mwi, ref wo, ref hitInfo.ShadingNormal, ref lightTroughtput, out fs, types: BrdfType.Diffuse); connectRays[tracedConnectRayCount].Radiance *= lightTroughtput * Vector.AbsDot(ref hitInfo.ShadingNormal, ref lwi) * fs; if (!connectRays[tracedConnectRayCount].Radiance.IsBlack()) { connectRays[tracedConnectRayCount].Pdf *= lightStrategyPdf; tracedConnectRayCount++; } } for (int i = 0; i < lightVertices; i++) { var lightThroughtput = lightPath[i].Throughput; connectRays[tracedConnectRayCount].Radiance = EyeThroughput * hitInfo.Color; connectRays[tracedConnectRayCount].Pdf = 1f; connectRays[tracedConnectRayCount].ConnectRay = new RayData(hitPoint, (hitPoint - lightPath[i].HitPoint).Normalize()); var lwi = -connectRays[tracedConnectRayCount].ConnectRay.Dir; connectRays[tracedConnectRayCount].Radiance *= lightThroughtput * Geometry.G(ref hitPoint, ref lightPath[i].HitPoint, ref hitInfo.Normal, ref lightPath[i].GeoNormal); // Vector.AbsDot(ref hitInfo.ShadingNormal, ref lwi); if (!connectRays[tracedConnectRayCount].Radiance.IsBlack()) { connectRays[tracedConnectRayCount].Pdf *= lightPath[i].Pdf*eyePdf; tracedConnectRayCount++; } } } RgbSpectrum f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref EyeThroughput, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), ref hitInfo.TextureData, out fPdf, out specularBounce); if ((fPdf <= 0.0f) || f.IsBlack()) { if (tracedConnectRayCount > 0) PathState = BDPTSamplerState.ConnectOnly; else { //Splat(consumer); eyeStop = true; } eyeStop = true; goto Connect; } eyePdf *= fPdf; EyeThroughput *= (f) / fPdf; if (eyeDepth > scene.MaxPathDepth) { float prob = Math.Max(EyeThroughput.Filter(), scene.RussianRuletteImportanceCap); if (prob >= Sample.GetLazyValue()) { EyeThroughput /= prob; eyePdf *= prob; } else { if (tracedConnectRayCount > 0) PathState = BDPTSamplerState.ConnectOnly; else { eyeStop = true; goto Connect; } eyeStop = true; goto Connect; } } PathRay.Org = hitPoint; PathRay.Dir = wi.Normalize(); PathState = BDPTSamplerState.PropagatePath; } @Connect: if (eyeStop && lightStop) { this.Splat(consumer); return; } }
public bool Match(ref SurfaceIntersectionData hit) { return hit.IsLight; }
public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer) { int currentTriangleIndex = 0; SurfaceIntersectionData hitInfo = null; #if VERBOSE try { #endif base.Advance(rayBuffer, consumer); 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() mutate = true; Radiance += attenuation * ((secRays[i].color)); pathWeight *= secRays[i].pdf; } } if (PathState == PathTracerPathState.ShadowRaysOnly) { Splat(consumer); return; } tracedShadowRayCount = 0; } RayHit rayHit = rayBuffer.rayHits[RayIndex]; 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(); } var wo = -PathRay.Dir; //If Hit light) if (hitInfo.IsLight) { if (specularBounce) { var lt = scene.GetLightByIndex(currentTriangleIndex); if (lt != null) { var le = (RgbSpectrum)(lt.Le(ref wo)); Radiance += Throughput * le; mutate = true; } } Splat(consumer); return; } var hitPoint = PathRay.Point(rayHit.Distance); var bsdf = hitInfo.MMaterial; 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(depth*2), Sample.GetLazyValue(depth * 3), Sample.GetLazyValue(depth * 4), ref ls, ltProb: Sample.GetLazyValue(depth)); for (int index = 0; index < ls.Length; index++) { if (ls[index].Pdf <= 0f) continue; secRays[tracedShadowRayCount].color = (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].color *= lightTroughtput * Vector.AbsDot(ref hitInfo.Normal, ref lwi) * fs; if (!secRays[tracedShadowRayCount].color.IsBlack()) { #if DEBUG RayDen.Library.Core.Components.Assert.IsNotNaN(secRays[tracedShadowRayCount].pdf); #endif 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 * 5), Sample.GetLazyValue(depth * 6), Sample.GetLazyValue(depth * 7), ref hitInfo.TextureData, out fPdf, out specularBounce); if ((fPdf <= 0.0f) || f.IsBlack()) { Splat(consumer); return; } pathWeight *= fPdf; Throughput *= f / fPdf; if (!mutate) mutate = Throughput.Filter() > Sample.GetLazyValue(depth * 8); if (depth > scene.MaxPathDepth) { float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap); if (prob >= Sample.GetLazyValue(depth * 9)) { Throughput /= prob; pathWeight *= prob; } 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 }
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 }
public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer) { base.Advance(rayBuffer, consumer); var rayHit = rayBuffer.rayHits[RayIndex]; depth++; bool missed = rayHit.Miss(); if (missed) { this.InitPath(pathIntegrator); return; } var hitPoint = PathRay.Point(rayHit.Distance); if (hitInfo == null) { hitInfo = new SurfaceIntersectionData(ref rayHit, true); } SurfaceSampler.GetIntersection(ref PathRay, ref rayHit, ref hitInfo); if (hitInfo.IsLight) { this.InitPath(pathIntegrator); engine.IncreasePhoton(); return; } float fPdf; Vector wi, wo = -PathRay.Dir; var bsdf = hitInfo.MMaterial; RgbSpectrum f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref ThroughtPut, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), ref hitInfo.TextureData, out fPdf, out specularBounce); if (fPdf <= 0f || f.IsBlack()) { this.InitPath(pathIntegrator); engine.IncreasePhoton(); return; } if (!specularBounce) { engine.StoreFlux(Alpha, ref hitPoint, ref hitInfo.ShadingNormal, wi, ref ThroughtPut); //InitPath(pathIntegrator); //return; } ThroughtPut *= f / fPdf; var p = scene.RussianRuletteImportanceCap; if (depth < scene.MaxPathDepth) { PathRay = new RayData(hitPoint, wi); } else if (Sample.GetLazyValue() < p) { ThroughtPut /= p; PathRay = new RayData(hitPoint, wi); } else { // Re-initialize the photon path engine.IncreasePhoton(); InitPath(pathIntegrator); } }