public override void InitPath(IPathProcessor buffer) { //Choose lightsource //Sample it base.InitPath(buffer); this.Sample = new Sample(pathIntegrator.Sampler); this.RayIndex = -1; float lspdf; int li = scene.SampleLights(this.Sample.GetLazyValue(), out lspdf); RayData ray; var ls = new LightSample(); bool done = false; while (!done) { scene.Lights[li].EvaluatePhoton( scene, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), out ls); done = ls.Pdf > 0f; } this.pathWeight = 10000 /(ls.Pdf * lspdf); ls.Spectrum.Mul(pathWeight); this.ThroughtPut = new RgbSpectrum(ls.Spectrum.ToArray()); this.PathRay = ls.LightRay; }
public void EvaluateShadow(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample[] result, float ltProb = 0f) { switch (scene.LightSamplingStrategy) { case LightSamplingStrategy.UniformOneLight: if (result == null) result = new LightSample[scene.ShadowRaysPerSample]; for (int i = 0; i < scene.ShadowRaysPerSample; i++) { int currentLightIndex = scene.SampleLights(ltProb <= 0f ? rnd.NextFloat() : ltProb); var light = scene.Lights[currentLightIndex]; var ls = result[i]??new LightSample(); ls.LightIndex = currentLightIndex; light.EvaluateShadow(ref point, ref n, u0, u1, u2, ref ls); //ls.Pdf *= (scene.ShadowRaysPerSample); result[i] = ls; } break; case LightSamplingStrategy.UniformAllLights: { var sm = new List<LightSample>(); foreach (var light in scene.Lights) { var ls = new LightSample(); light.EvaluateShadow(ref point, ref n, u0, u1, u2, ref ls); if (ls.Pdf > 0f) sm.Add(ls); } result = sm.ToArray(); } break; } }
public override void InitPath(IPathProcessor buffer) { base.InitPath(buffer); scene = pathIntegrator.Scene; this.Sample = new Sample(pathIntegrator.Sampler); this.RayIndex = -1; float lspdf; int li = scene.SampleLights(this.Sample.GetLazyValue(), out lspdf); var ls = new LightSample(); bool done = false; while (!done) { scene.Lights[li].EvaluatePhoton( scene, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), out ls); done = ls.Pdf > 0f; } var pathWeight = (ls.Pdf * lspdf); this.ThroughtPut = ((RgbSpectrum)(ls.Spectrum) / pathWeight); this.PathRay = ls.LightRay; }
private IColorType SampleProfile(ref LightSample ls, EmissionProfile profile) { if (profile.ProfileMode == ProfileMode.EmissionValue) { return ColorManager.Instance.Convert(profile.EmissionSpectra, SpectrumType.Illuminant); } var c = (RgbSpectrum)profile.EmissionTexture.Sample(ls.U, ls.V); return ColorManager.Instance.Convert(ref c); }
public void EvaluatePhoton(IRayEngineScene scene, float u0, float u1, float u2, float u3, float u4, out LightSample result) { result = new LightSample(); Vector dir = MC.UniformSampleSphere(u0, u1); result.LightRay = new RayData(ref Position, ref dir, 1e-4f, 1e4f); result.Pdf = MathLab.INV4PI; result.Spectrum = (Power * MathLab.M_PI * 4f); }
public virtual void EvaluateShadow(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample result) { #if VERBOSE try{ #endif if (result == null) result = new LightSample(); if (true) { var wi = MC.CosineSampleHemisphere(u1, u2); Vector v1, v2; Vector.CoordinateSystem(ref n, out v1, out v2); //Console.WriteLine("Should share frame(ONB) with bsdf somehow"); wi = new Vector( v1.x*wi.x + v2.x*wi.y + n.x*wi.z, v1.y*wi.x + v2.y*wi.y + n.y*wi.z, v1.z*wi.x + v2.z*wi.y + n.z*wi.z).Normalize(); result.LightRay = new RayData(ref point, ref wi, 1e-4f, float.MaxValue); result.Distance = 1e4f; result.Spectrum = Le(ref wi); result.Pdf = Math.Abs(wi.z * MathLab.INVPI); //var i = ((RgbSpectrumInfo) result.Spectrum).y(); //result.Pdf *= i; } else { Vector wi = MC.UniformSampleSphere(u0, u1); result.LightRay = new RayData(ref point, ref wi, 1e-4f, float.MaxValue); result.Pdf = 1f / (4f * MathLab.M_PI); result.Spectrum = Le(ref wi); //var i = ((RgbSpectrumInfo)result.Spectrum).y(); //result.Pdf *= i; } #if VERBOSE }catch(Exception ex) { Tracer.TraceLine(ex.Message); Tracer.TraceLine(ex.StackTrace); throw; } #endif }
public void EvaluateShadow(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample[] result, float ltProb = 0f) { switch (scene.LightSamplingStrategy) { case LightSamplingStrategy.UniformOneLight: if (result == null) result = new LightSample[scene.ShadowRaysPerSample]; for (int i = 0; i < scene.ShadowRaysPerSample; i++) { int currentLightIndex = scene.SampleLights(ltProb <= 0f ? rnd.NextFloat() : ltProb); var light = scene.Lights[currentLightIndex]; var ls = result[i] ?? new LightSample() { LightRay = new RayData() { Org = point } }; ls.LightIndex = currentLightIndex; light.SampleSpatialDirect(ref point, ref n, u0, u1, u2, ref ls); ls.LightRay.maxT = ls.Distance; if (light is BaseInfiniteLight) { ls.Color = ColorManager.Instance.Convert(light.Le(ref ls.LightRay.Dir).ToArray()); } else { ls.Color = this.SampleProfile(ref ls, light.Profile); } //ls.Pdf *= (scene.ShadowRaysPerSample); result[i] = ls; } break; case LightSamplingStrategy.UniformAllLights: { var sm = new List<LightSample>(); foreach (var light in scene.Lights) { var ls = new LightSample(); light.EvaluateShadow(ref point, ref n, u0, u1, u2, ref ls); if (ls.Pdf > 0f) sm.Add(ls); } result = sm.ToArray(); } throw new NotImplementedException("UniformAllLights not implemented"); break; } }
public void EvaluateShadow(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample result) { if (result == null) result = new LightSample(); var dir = -(Position - point); var l2 = dir.Length2(); var l = MathLab.Sqrt(l2); dir.Normalize(); result.Pdf = MC.UniformSpherePdf(); result.LightRay = new RayData(ref point, ref dir, 1e-4f, l - 1e-4f); result.Distance = l; float theta = Vector.SphericalTheta(ref dir); var i = Profile.Evaluate(Vector.SphericalPhi(ref dir) * MathLab.INVTWOPI, theta * MathLab.INVPI); i.Div(l); var p = (ISpectrum) Power; i.Mul(ref p); result.Spectrum = i; }
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]; 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.lastPdfW = 1.0f; this.tracedShadowRayCount = 0; this.depth = 0; this.specularBounce = true; if (ls == null) ls = new LightSample(); }
public void EvaluateShadow(BaseBxdf bsdfSample,float u0, float u1, float u2, ref LightSample[] result, float ltProb = 0f) { switch (scene.LightSamplingStrategy) { case LightSamplingStrategy.UniformOneLight: if (result == null) result = new LightSample[scene.ShadowRaysPerSample]; for (int i = 0; i < scene.ShadowRaysPerSample; i++) { int currentLightIndex = scene.SampleLights(ltProb <= 0f ? rnd.NextFloat() : ltProb); var lt0 = scene.Lights[currentLightIndex] as INewLight; var lt1 = scene.Lights[currentLightIndex] as ILight; var ls = result[i] ?? new LightSample(); ls.LightIndex = currentLightIndex; if (lt0 == null) lt1.EvaluateShadow(ref bsdfSample.HitPoint.HitPoint, ref bsdfSample.HitPoint.GeoNormal, u0, u1, u2, ref ls); else lt0.EvaluateShadow(bsdfSample, u0, u1, u2, ref ls); //ls.Pdf *= (scene.ShadowRaysPerSample); result[i] = ls; } break; case LightSamplingStrategy.UniformAllLights: { var sm = new List<LightSample>(); foreach (var light in scene.Lights.Cast<INewLight>()) { var ls = new LightSample(); light.EvaluateShadow(bsdfSample, u0, u1, u2, ref ls); if (ls.Pdf > 0f) sm.Add(ls); } result = sm.ToArray(); } break; } }
public void EvaluateShadow(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample result) { if (result == null) result = new LightSample(); var l = Position - (point + MC.UniformSampleSphere(u0, u1) * Radius); // vector to random point on source var Dist = l.Length; // distance to light source result.Distance = Dist; result.Pdf = MC.UniformSpherePdf(); result.LightRay = new RayData(point, l/Dist, 1e-4f, Dist - 1e-4f); // result.Spectrum = GlobalConfiguration.Instance.SpectralRendering ? (ISpectrum) (Spectra / Dist) : (Power / Dist); float theta = Vector.SphericalTheta(ref result.LightRay.Dir); var i = Profile.Evaluate(Vector.SphericalPhi(ref result.LightRay.Dir) * MathLab.INVTWOPI, theta * MathLab.INVPI); i.Div(Dist); var p = (ISpectrum)Power; i.Mul(ref p); result.Spectrum = i; }
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 void SampleSpatialDirect(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample ls) { var wi = MC.CosineSampleHemisphere(u1, u2); Vector v1, v2; Vector.CoordinateSystem(ref n, out v1, out v2); //Console.WriteLine("Should share frame(ONB) with bsdf somehow"); ls.LightRay.Dir = new Vector( v1.x * wi.x + v2.x * wi.y + n.x * wi.z, v1.y * wi.x + v2.y * wi.y + n.y * wi.z, v1.z * wi.x + v2.z * wi.y + n.z * wi.z).Normalize(); ls.Distance = 1e4f; ls.Pdf = wi.z * MathLab.INVPI; }
public void SampleSpatialDirect(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample ls) { var l = Position - (point + MC.UniformSampleSphere(u0, u1) * Radius); // vector to random point on source ls.Distance = l.Length; // distance to light source ls.Pdf = MC.UniformSpherePdf(); ls.LightRay.Dir = l / ls.Distance; }
public void SampleSpatialDirect(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample ls) { var dir = -(Position - point); var l2 = dir.Length2(); var l = MathLab.Sqrt(l2); dir.Normalize(); ls.Pdf = MC.UniformSpherePdf(); ls.Distance = l; float theta = Vector.SphericalTheta(ref dir); var i = Profile.Evaluate(Vector.SphericalPhi(ref dir) * MathLab.INVTWOPI, theta * MathLab.INVPI); i.Div(l); }
public void EvaluatePhoton(float u0, float u1, float u2, float u3, float u4, out LightSample[] result, float ltProb = 0f) { throw new NotImplementedException(); }
public Color PathTrace(Ray ray, HitRecord record, List <List <Sample> > subPathSamples, LightSample lightSample) { float q = 0f; int depth = 0; Color pixelColor = new Color(0, 0, 0); Color alpha = new Color(1, 1, 1); bool isGeneratedFromRefraction = false; while (depth < Constants.MaximalPathLength) { if (record == null) { return(pixelColor); } //Select one light at random ILight light = Randomizer.PickRandomLight(lights); //Sample that light light.Sample(record, lightSample); if (isGeneratedFromRefraction && record.HitObject.Light != null) { isGeneratedFromRefraction = false; pixelColor.Append(record.HitObject.Light.LightColor); } pixelColor.Append(alpha.Mult(Shade(record, lightSample)).Div(lightSample.Pdf)); //Break with Russian roulette if (depth > 2) { q = 0.5f; if (random.NextDouble() <= q) { return(pixelColor); } } List <Sample> directionSamples = subPathSamples[depth]; //Create the next Ray if (record.Material is LambertMaterial || record.Material is BlinnPhongMaterial) { Sample directionSample = Randomizer.PickRandomSample(directionSamples); Vector3 direction = UniformHemisphereSample(directionSample.X, directionSample.Y, record.SurfaceNormal); record = scene.Intersect(new Ray(record.IntersectionPoint, direction)); if (record == null) { break; } alpha = alpha.Mult(record.Material.Diffuse.Div(1 - q)); } else if (record.Material is MirrorMaterial) { record = scene.Intersect(record.CreateReflectedRay()); isGeneratedFromRefraction = true; } else if (record.Material is RefractiveMaterial) { isGeneratedFromRefraction = true; float fresnel = Reflectance(record); //Pick refraction / reflection path with p=0.5 each if (random.NextDouble() < fresnel) { record = scene.Intersect(record.CreateReflectedRay()); alpha = alpha.Mult(fresnel); } else { record = scene.Intersect(record.CreateRefractedRay()); alpha = alpha.Mult(1 - fresnel); } } depth++; } return(pixelColor); }
public new Vector3 GetSamplePoint(LightSample sample) { return(Intersectable.GetSamplePoint(sample)); }
public void EvaluatePhoton(IRayEngineScene scen, float u0, float u1, float u2, float u3, float u4, out LightSample result) { result = new LightSample(); var scene = (RayEngineScene)scen; float b0, b1, b2; Point orig; int index; var tri = SampleTriangle(u4, out index); tri.Sample(scene.Vertices, u0, u1, out orig, out b0, out b1, out b2); var TriangleNormal = triangleSampleData[index].Item2; var area = triangleSampleData[index].Item1; // Ray direction var sampleN = -TriangleNormal; Vector dir = MC.UniformSampleSphere(u2, u3); float rdotN = Normal.Dot(ref dir, ref sampleN); if (rdotN < 0f) { dir *= -1f; rdotN = -rdotN; } result.LightRay = new RayInfo(ref orig, ref dir); result.Pdf = ((MathLab.INVTWOPI / area) * (1f / mesh.TrianglesCount)); result.Spectrum = Profile.Evaluate(b0, b1); result.Spectrum.Mul(rdotN); }
public void EvaluateShadow(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample result) { int tries = 0; #if VERBOSE try { #endif if (result == null) result = new LightSample(); var samplePoint = new Point(); float b0, b1, b2; int maxTries = 1; startTry: var index = Math.Max(0, Math.Min(triangleSampleData.Length - 1, (int)(u0 * (mesh.EndTriangle - mesh.StartTriangle)))); scene.Triangles[mesh.StartTriangle + index].Sample(scene.Vertices, u2, u1, out samplePoint, out b0, out b1, out b2); //TriangleDataInfo.Sample(ref scene.Triangles[mesh.StartTriangle + index], scene.Vertices, u2, u1, out samplePoint, out b0, out b1, out b2); var area = triangleSampleData[index].Item1; //tri.AreaV(scene.Vertices); //var sampleN = TriangleNormal; //var N = n; Vector wi = samplePoint - point; //wi.Normalize(); float distanceSquared = wi.Length2(); float distance = MathLab.Sqrt(distanceSquared); wi /= distance; var nw = -wi; float sampleNdotMinusWi = Normal.Dot(ref triangleSampleData[index].Item2, ref nw); float NdotWi = Normal.Dot(ref n, ref wi); if ((sampleNdotMinusWi <= 0f) || (NdotWi <= 0f)) { tries++; if (tries > maxTries) { return; } goto startTry; } result.Pdf = //((1f / area) * distanceSquared / sampleNdotMinusWi) * (1f / mesh.TrianglesCount) * (1f / Math.Max(1, tries + 1)); (distanceSquared / (sampleNdotMinusWi * area)) * 1f / mesh.TrianglesCount * (1f / Math.Max(1, tries + 1)); // Using 0.01 instead of 0.0 to cut down fireflies if (result.Pdf <= 0.01f) { result.Pdf = 0f; result.Spectrum = GlobalConfiguration.Instance.SpectralRendering ? (ISpectrum)ZeroCSpectrumArray : this.RgbSpectrumZeroArray; return; } result.LightRay = new RayInfo(point, wi, 1e-4f, 1e3f); //, MathLab.RAY_EPSILON, distance - MathLab.RAY_EPSILON); result.Distance = distance; result.Spectrum = Profile.Evaluate(b0, b1); #if VERBOSE } catch (Exception ex) { Tracer.TraceLine(ex.Message + ex.StackTrace); Tracer.TraceLine("Triangle data offset " + (mesh.StartTriangle).ToString() + "of " + triangleSampleData.Length); throw ex; } #endif }
public Color Integrate(Ray ray, IIntersectable objects, List <ILight> lights, ISampler sampler, List <List <Sample> > subPathSamples, LightSample lightSample) { HitRecord record = objects.Intersect(ray); Color returnColor = new Color(0, 0, 0); if (record != null) { foreach (ILight light in lights) { Vector3 lightDirection = light.GetLightDirection(record.IntersectionPoint); Vector3 hitPos = record.IntersectionPoint; Vector3 offset = record.RayDirection; offset = -offset; offset *= 0.001f; hitPos += offset; Ray shadowRay = new Ray(hitPos, lightDirection); HitRecord shadowHit = objects.Intersect(shadowRay); Vector3 distance = Vector3.Subtract(light.Position, hitPos); //DEBUGGING /*if (shadowHit != null && (shadowHit.Distance > distance.Length)) * { * returnColor.Append(record.HitObject.Material.Shade(record, light.GetLightDirection(record.IntersectionPoint)).Mult(light.GetIncidentColor(record.IntersectionPoint))); * }*/ returnColor.Append(record.HitObject.Material.Shade(record, light.GetLightDirection(record.IntersectionPoint)).Mult(light.GetIncidentColor(record.IntersectionPoint))); } } return(returnColor); }
public void EvaluatePhoton(IRayEngineScene scene, float u0, float u1, float u2, float u3, float u4, out LightSample result) { result = new LightSample(); var dir = MC.UniformSampleSphere(u0, u1); result.LightRay = new RayData(ref Position, ref dir, 1e-4f, 1e4f); result.Pdf = MathLab.INV4PI/Radius; float theta = Vector.SphericalTheta(ref result.LightRay.Dir); var i = (RgbSpectrumInfo)Profile.Evaluate(Vector.SphericalPhi(ref result.LightRay.Dir) * MathLab.INVTWOPI, theta * MathLab.INVPI); result.Spectrum = i * Radius * MathLab.M_PI * 4f; }
public void getSamples(ShadingState state) { if (getNumSamples() <= 0) { return; } Vector3 wc = Point3.sub(center, state.getPoint(), new Vector3()); float l2 = wc.LengthSquared(); if (l2 <= r2) { return; // inside the sphere? } // top of the sphere as viewed from the current shading point float topX = wc.x + state.getNormal().x *radius; float topY = wc.y + state.getNormal().y *radius; float topZ = wc.z + state.getNormal().z *radius; if (state.getNormal().dot(topX, topY, topZ) <= 0) { return; // top of the sphere is below the horizon } float cosThetaMax = (float)Math.Sqrt(Math.Max(0, 1 - r2 / Vector3.dot(wc, wc))); OrthoNormalBasis basis = OrthoNormalBasis.makeFromW(wc); int samples = state.getDiffuseDepth() > 0 ? 1 : getNumSamples(); float scale = (float)(2 * Math.PI * (1 - cosThetaMax)); Color c = Color.mul(scale / samples, radiance); for (int i = 0; i < samples; i++) { // random offset on unit square double randX = state.getRandom(i, 0, samples); double randY = state.getRandom(i, 1, samples); // cone sampling double cosTheta = (1 - randX) * cosThetaMax + randX; double sinTheta = Math.Sqrt(1 - cosTheta * cosTheta); double phi = randY * 2 * Math.PI; Vector3 dir = new Vector3((float)(Math.Cos(phi) * sinTheta), (float)(Math.Sin(phi) * sinTheta), (float)cosTheta); basis.transform(dir); // check that the direction of the sample is the same as the // normal float cosNx = Vector3.dot(dir, state.getNormal()); if (cosNx <= 0) { continue; } float ocx = state.getPoint().x - center.x; float ocy = state.getPoint().y - center.y; float ocz = state.getPoint().z - center.z; float qa = Vector3.dot(dir, dir); float qb = 2 * ((dir.x * ocx) + (dir.y * ocy) + (dir.z * ocz)); float qc = ((ocx * ocx) + (ocy * ocy) + (ocz * ocz)) - r2; double[] t = Solvers.solveQuadric(qa, qb, qc); if (t == null) { continue; } LightSample dest = new LightSample(); // compute shadow ray to the sampled point dest.setShadowRay(new Ray(state.getPoint(), dir)); // FIXME: arbitrary bias, should handle as in other places dest.getShadowRay().setMax((float)t[0] - 1e-3f); // prepare sample dest.setRadiance(c, c); dest.traceShadow(state); state.addSample(dest); } }
public Color Integrate(Ray ray, IIntersectable objects, List <ILight> lights, ISampler sampler, List <List <Sample> > subPathSamples, LightSample lightSample) { scene = objects; this.lights = lights; this.sampler = sampler; HitRecord record = scene.Intersect(ray); if (record == null) { if (SkyBox.IsSkyBoxLoaded()) { return(SkyBox.GetSkyBoxColor(ray)); } return(new Color(0, 0, 0)); } if (record.HitObject.Light != null) { return(record.HitObject.Light.LightColor); } return(PathTrace(ray, record, subPathSamples, lightSample)); }
public Color Integrate(Ray ray, IIntersectable objects, List <ILight> lights, ISampler sampler, List <List <Sample> > subPathSamples, LightSample lightSample) { HitRecord record = objects.Intersect(ray); if (record != null) { return(new Color(1, 1, 1)); } else { return(new Color(0, 0, 0)); } }
public void getSamples(ShadingState state) { if (meshlight.numSamples == 0) { return; } Vector3 n = state.getNormal(); Point3 p = state.getPoint(); // vector towards each vertex of the light source Vector3 p0 = Point3.sub(meshlight.getPoint(meshlight.triangles[tri3 + 0]), p, new Vector3()); // cull triangle if it is facing the wrong way if (Vector3.dot(p0, ng) >= 0) { return; } Vector3 p1 = Point3.sub(meshlight.getPoint(meshlight.triangles[tri3 + 1]), p, new Vector3()); Vector3 p2 = Point3.sub(meshlight.getPoint(meshlight.triangles[tri3 + 2]), p, new Vector3()); // if all three vertices are below the hemisphere, stop if (Vector3.dot(p0, n) <= 0 && Vector3.dot(p1, n) <= 0 && Vector3.dot(p2, n) <= 0) { return; } p0.normalize(); p1.normalize(); p2.normalize(); float dot = Vector3.dot(p2, p0); Vector3 h = new Vector3(); h.x = p2.x - dot * p0.x; h.y = p2.y - dot * p0.y; h.z = p2.z - dot * p0.z; float hlen = h.Length(); if (hlen > 1e-6f) { h.div(hlen); } else { return; } Vector3 n0 = Vector3.cross(p0, p1, new Vector3()); float len0 = n0.Length(); if (len0 > 1e-6f) { n0.div(len0); } else { return; } Vector3 n1 = Vector3.cross(p1, p2, new Vector3()); float len1 = n1.Length(); if (len1 > 1e-6f) { n1.div(len1); } else { return; } Vector3 n2 = Vector3.cross(p2, p0, new Vector3()); float len2 = n2.Length(); if (len2 > 1e-6f) { n2.div(len2); } else { return; } float cosAlpha = MathUtils.clamp(-Vector3.dot(n2, n0), -1.0f, 1.0f); float cosBeta = MathUtils.clamp(-Vector3.dot(n0, n1), -1.0f, 1.0f); float cosGamma = MathUtils.clamp(-Vector3.dot(n1, n2), -1.0f, 1.0f); float alpha = (float)Math.Acos(cosAlpha); float beta = (float)Math.Acos(cosBeta); float gamma = (float)Math.Acos(cosGamma); float area = alpha + beta + gamma - (float)Math.PI; float cosC = MathUtils.clamp(Vector3.dot(p0, p1), -1.0f, 1.0f); float salpha = (float)Math.Sin(alpha); float product = salpha * cosC; // use lower sampling depth for diffuse bounces int samples = state.getDiffuseDepth() > 0 ? 1 : meshlight.numSamples; Color c = Color.mul(area / samples, meshlight.radiance); for (int i = 0; i < samples; i++) { // random offset on unit square double randX = state.getRandom(i, 0, samples); double randY = state.getRandom(i, 1, samples); float phi = (float)randX * area - alpha + (float)Math.PI; float sinPhi = (float)Math.Sin(phi); float cosPhi = (float)Math.Cos(phi); float u = cosPhi + cosAlpha; float v = sinPhi - product; float q = (-v + cosAlpha * (cosPhi * -v + sinPhi * u)) / (salpha * (sinPhi * -v - cosPhi * u)); float q1 = 1.0f - q * q; if (q1 < 0.0f) { q1 = 0.0f; } float sqrtq1 = (float)Math.Sqrt(q1); float ncx = q * p0.x + sqrtq1 * h.x; float ncy = q * p0.y + sqrtq1 * h.y; float ncz = q * p0.z + sqrtq1 * h.z; dot = p1.dot(ncx, ncy, ncz); float z = 1.0f - (float)randY * (1.0f - dot); float z1 = 1.0f - z * z; if (z1 < 0.0f) { z1 = 0.0f; } Vector3 nd = new Vector3(); nd.x = ncx - dot * p1.x; nd.y = ncy - dot * p1.y; nd.z = ncz - dot * p1.z; nd.normalize(); float sqrtz1 = (float)Math.Sqrt(z1); Vector3 result = new Vector3(); result.x = z * p1.x + sqrtz1 * nd.x; result.y = z * p1.y + sqrtz1 * nd.y; result.z = z * p1.z + sqrtz1 * nd.z; // make sure the sample is in the right hemisphere - facing in // the right direction if (Vector3.dot(result, n) > 0 && Vector3.dot(result, state.getGeoNormal()) > 0 && Vector3.dot(result, ng) < 0) { // compute intersection with triangle (if any) Ray shadowRay = new Ray(state.getPoint(), result); if (!intersectTriangleKensler(shadowRay)) { continue; } LightSample dest = new LightSample(); dest.setShadowRay(shadowRay); // prepare sample dest.setRadiance(c, c); dest.traceShadow(state); state.addSample(dest); } } }
public abstract Color Sample(Ray3 ray, LightSample lightSample, Vector3 normal, Vector3 position, Vector2 textureCoordinates = null);
public virtual void EvaluatePhoton(IRayEngineScene scen, float u0, float u1, float u2, float u3, float u4, out LightSample result) { result = new LightSample(); var scene = (RayEngineScene) scen; var worldCenter = scene.SceneGeometry.BoundingSphereCenter; var worldRadius = scene.SceneGeometry.BoundingSphereRadius * 1.01f; var p1 = worldCenter + worldRadius * MC.UniformSampleSphere(u0, u1); var p2 = worldCenter + worldRadius * MC.UniformSampleSphere(u2, u3); // Construct ray between p1 and p2 result.LightRay = new RayData(p1, (p2 - p1).Normalize(), 1e-4f, 1e4f); // Compute InfiniteAreaLight ray weight Vector toCenter = (worldCenter - p1).Normalize(); var rayDir = result.LightRay.Dir; float costheta = MathLab.AbsDot(ref toCenter, ref rayDir); result.Pdf = costheta / (4f * MathLab.M_PI * MathLab.M_PI * worldRadius * worldRadius); result.Spectrum = Le(ref result.LightRay.Dir); }
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 }
public void getSamples(ShadingState state) { if (samples == null) { int n = state.getDiffuseDepth() > 0 ? 1 : numSamples; for (int i = 0; i < n; i++) { // random offset on unit square, we use the infinite version of // getRandom because the light sampling is adaptive double randX = state.getRandom(i, 0, n); double randY = state.getRandom(i, 1, n); int x = 0; while (randX >= colHistogram[x] && x < colHistogram.Length - 1) { x++; } float[] rowHistogram = imageHistogram[x]; int y = 0; while (randY >= rowHistogram[y] && y < rowHistogram.Length - 1) { y++; } // sample from (x, y) float u = (float)((x == 0) ? (randX / colHistogram[0]) : ((randX - colHistogram[x - 1]) / (colHistogram[x] - colHistogram[x - 1]))); float v = (float)((y == 0) ? (randY / rowHistogram[0]) : ((randY - rowHistogram[y - 1]) / (rowHistogram[y] - rowHistogram[y - 1]))); float px = ((x == 0) ? colHistogram[0] : (colHistogram[x] - colHistogram[x - 1])); float py = ((y == 0) ? rowHistogram[0] : (rowHistogram[y] - rowHistogram[y - 1])); float su = (x + u) / colHistogram.Length; float sv = (y + v) / rowHistogram.Length; float invP = (float)Math.Sin(sv * Math.PI) * jacobian / (n * px * py); Vector3 dir = getDirection(su, sv); basis.transform(dir); if (Vector3.dot(dir, state.getGeoNormal()) > 0) { LightSample dest = new LightSample(); dest.setShadowRay(new Ray(state.getPoint(), dir)); dest.getShadowRay().setMax(float.MaxValue); Color radiance = texture.getPixel(su, sv); dest.setRadiance(radiance, radiance); dest.getDiffuseRadiance().mul(invP); dest.getSpecularRadiance().mul(invP); dest.traceShadow(state); state.addSample(dest); } } } else { if (state.getDiffuseDepth() > 0) { for (int i = 0; i < numLowSamples; i++) { if (Vector3.dot(lowSamples[i], state.getGeoNormal()) > 0 && Vector3.dot(lowSamples[i], state.getNormal()) > 0) { LightSample dest = new LightSample(); dest.setShadowRay(new Ray(state.getPoint(), lowSamples[i])); dest.getShadowRay().setMax(float.MaxValue); dest.setRadiance(lowColors[i], lowColors[i]); dest.traceShadow(state); state.addSample(dest); } } } else { for (int i = 0; i < numSamples; i++) { if (Vector3.dot(samples[i], state.getGeoNormal()) > 0 && Vector3.dot(samples[i], state.getNormal()) > 0) { LightSample dest = new LightSample(); dest.setShadowRay(new Ray(state.getPoint(), samples[i])); dest.getShadowRay().setMax(float.MaxValue); dest.setRadiance(colors[i], colors[i]); dest.traceShadow(state); state.addSample(dest); } } } } }
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 void EvaluateShadow(ref Point point, ref Normal normal, float u0, float u1, float u2, ref LightSample result) { if (result == null) result = new LightSample(); var samplePoint = new Point(); float b0, b1, b2; scene.Triangles[triangleIndex].Sample(scene.Vertices, u0, u1, out samplePoint, out b0, out b1, out b2); var sampleN = //-scene.Triangles[triangleIndex].ComputeNormal(scene.Vertices); //scene.Triangles[triangleIndex].InterpolateNormal(scene.Vertices, b0, b1); TriangleNormal.Normalize(); var N = normal.Normalize(); Vector wi = samplePoint - point; float distanceSquared = wi.Length2(); float distance = MathLab.Sqrt(distanceSquared); wi /= distance; var nw = -wi; float sampleNdotMinusWi = Normal.Dot(ref sampleN, ref nw); float NdotWi = Normal.Dot(ref N, ref wi); if ((sampleNdotMinusWi <= 0f) || (NdotWi <= 0f)) { result.Pdf = 0f; result.LightRay = new RayData(); result.Spectrum = GlobalConfiguration.Instance.SpectralRendering ? ZeroCSpectrumArray : RgbSpectrumZeroArray; return; } result.LightRay = new RayData(ref point, ref wi, #if SHORT_RAYS MathLab.RAY_EPSILON, distance - MathLab.RAY_EPSILON); #else MathLab.RAY_EPSILON, distanceSquared); #endif result.Pdf = (distanceSquared / (sampleNdotMinusWi * area)); // Using 0.1 instead of 0.0 to cut down fireflies if (result.Pdf <= 0.1f) { result.Pdf = 0f; result.Spectrum = GlobalConfiguration.Instance.SpectralRendering ? ZeroCSpectrumArray : RgbSpectrumZeroArray; return; } #if DEBUG Assert.IsNotNaN(result.Pdf); #endif result.Distance = distance; result.Spectrum = Profile.Evaluate(b0, b1); }
public Vector3 GetSamplePoint(LightSample sample) { throw new NotImplementedException(); }
public Vector3 GetSamplePoint(LightSample sample) { throw new NotSupportedException(); }
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 Color Integrate(Ray ray, IIntersectable objects, List <ILight> lights, ISampler sampler, List <List <Sample> > subPathSamples, LightSample lightSample) { shadowIntegrator = new ShadowIntegrator(); Color returnColor = new Color(0, 0, 0); HitRecord record = objects.Intersect(ray); if (record != null) { if (!(record.Material is MirrorMaterial)) { returnColor.Append(shadowIntegrator.Integrate(ray, objects, lights, sampler, subPathSamples, lightSample)); } if (record.Material is MirrorMaterial && record.Material.Specular.R > 0 && record.Material.Specular.G > 0 && record.Material.Specular.B > 0) { returnColor.Append(Reflection(ray, record, 0, returnColor, objects, lights, sampler, subPathSamples, lightSample)); } } else { if (SkyBox.IsSkyBoxLoaded()) { returnColor = SkyBox.GetSkyBoxColor(ray); } } return(returnColor); }
public new Vector3 GetSamplePoint(LightSample sample) { Triangle sampleTriangle = Triangles[(int)Math.Floor(new Random().NextDouble() * Triangles.Count)]; return(sampleTriangle.GetSamplePoint(sample)); }
public override void GenerateLiRays(IRayEngineScene scn, Sample sample, ref RayData ray, VolumeComputation comp) { comp.Reset(); var scene = (RayEngineScene)(scn); var sigs = sig_s; comp.EmittedLight = lightEmission; float t0, t1; if (!region.Intersect(ray, out t0, out t1)) return; if (sigs.IsBlack() || (scene.Lights.Length < 1)) { float distance = t1 - t0; comp.EmittedLight = lightEmission * distance; } else { // Prepare for volume integration stepping float distance = t1 - t0; var nSamples = MathLab.Ceil2UInt(distance / stepSize); float step = distance / nSamples; RgbSpectrum Tr = new RgbSpectrum(1f); RgbSpectrum Lv = new RgbSpectrum(); var p = ray.Point(t0); float offset = sample.GetLazyValue(); t0 += offset * step; //Vector pPrev; for (var i = 0; i < nSamples; ++i, t0 += step) { //pPrev = p; p = ray.Point(t0); Sigma_s(ref p, out sigs); //sigs = NoiseProvider.Instance.Noise3D(((Vector)p).Normalize()); Lv += lightEmission; if (!sigs.IsBlack() && (scene.Lights.Length) > 0) { // Select the light to sample float lightStrategyPdf; var light = scene.Lights[scene.SampleLights(sample.GetLazyValue(), out lightStrategyPdf)]; // Select a point on the light surface float lightPdf; Normal fakeNorml = new Normal(0f, 0f, 1f); LightSample ls = new LightSample(); light.EvaluateShadow(ref p, ref fakeNorml, sample.GetLazyValue(), sample.GetLazyValue(), sample.GetLazyValue(), ref ls); var lightColor = (RgbSpectrumInfo)(ls.Spectrum); lightPdf = ls.Pdf; comp.Rays[comp.RayCount] = ls.LightRay; if ((lightPdf > 0f) && !lightColor.IsBlack()) { comp.ScatteredLight[comp.RayCount] =(RgbSpectrum)(Tr * sigs * lightColor * MathLab.Exp(-distance) * ((Density(ref p) * step) / (4f * MathLab.M_PI * lightPdf * lightStrategyPdf))); comp.RayCount++; } } comp.EmittedLight = Lv * step; } } }
public ExplicitLightVertex CreateLightVertex(Sample sample, GeometryVertex vertex) { int currentLightIndex = scene.SampleLights(sample.GetLazyValue()); var light = scene.Lights[currentLightIndex]; var ls = new LightSample(); light.EvaluateShadow(ref vertex.Point, ref vertex.GeometryNormal, sample.GetLazyValue(), sample.GetLazyValue(), sample.GetLazyValue(), ref ls); if (ls.Pdf <= 0f) { throw new Exception(); } /* secRays[tracedShadowRayCount].color = new 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, out fs, BrdfType.Diffuse); secRays[tracedShadowRayCount].color *= lightTroughtput * Vector.AbsDot(ref hitInfo.ShadingNormal, ref lwi) * fs; */ return new ExplicitLightVertex() { }; }
public void SampleSpatialDirect(ref Point point, ref Normal n, float u0, float u1, float u2, ref LightSample ls) { int tries = 0; #if VERBOSE try { #endif var samplePoint = new Point(); float b0, b1, b2; int maxTries = 1; startTry: TriangleDataInfo.Sample(ref scene.Triangles[triangleIndex], scene.Vertices, u2, u1, out samplePoint, out b0, out b1, out b2); var triangleNormal = TriangleNormal; //tri.AreaV(scene.Vertices); //var sampleN = TriangleNormal; //var N = n; ls.U = b0; ls.V = b1; Vector wi = samplePoint - point; //wi.Normalize(); float distanceSquared = wi.Length2(); ls.Distance = MathLab.Sqrt(distanceSquared); wi /= ls.Distance; var nw = -wi; float sampleNdotMinusWi = Normal.Dot(ref triangleNormal, ref nw); float NdotWi = Normal.Dot(ref n, ref wi); if ((sampleNdotMinusWi <= 0f) || (NdotWi <= 0f)) { tries++; if (tries > maxTries) { ls.Pdf = 0f; return; } goto startTry; } ls.Pdf = //((1f / area) * distanceSquared / sampleNdotMinusWi) * (1f / mesh.TrianglesCount) * (1f / Math.Max(1, tries + 1)); (distanceSquared / (sampleNdotMinusWi * area)) * (1f / Math.Max(1, tries + 1)); // Using 0.01 instead of 0.0 to cut down fireflies if (ls.Pdf <= 0.01f) { ls.Pdf = 0f; return; } ls.LightRay.Dir = wi; //, MathLab.RAY_EPSILON, distance - MathLab.RAY_EPSILON); #if VERBOSE } catch (Exception ex) { Tracer.TraceLine(ex.Message + ex.StackTrace); //Tracer.TraceLine("Triangle data offset "+ (mesh.StartTriangle).ToString() + "of " + triangleSampleData.Length); throw ex; } #endif }
public override void Advance(RayBuffer rayBuffer, SampleBuffer consumer, Action<PathSamplerBase> onRestart) { int currentTriangleIndex = 0; SurfaceIntersectionData hitInfo = null; #if VERBOSE try { #endif base.Advance(rayBuffer, consumer, onRestart); if (((this.PathState == GenericPathSamplerState.Connection))) { for (int i = 0; i < tracedShadowRayCount; i++) { connections[i].Connected = rayBuffer.rayHits[connections[i].CurrentShadowRayIndex].Miss(); } PathState = GenericPathSamplerState.Evaluation; return; } var rayHit = rayBuffer.rayHits[RayIndex]; depth++; bool missed = rayHit.Index == 0xffffffffu; if (missed) { if (depth <= scene.MaxPathDepth) { vertices[currentVertice] = new EnvironmentPathElement() { Throughput = SampleEnvironment(-PathRay.Dir) }; } if (PathState == GenericPathSamplerState.Initialized || PathState == GenericPathSamplerState.Sampling) { PathState = GenericPathSamplerState.Connection; return; } } // Something was hit hitInfo = SurfaceSampler.GetIntersection(ref PathRay, ref rayHit); currentTriangleIndex = (int)rayHit.Index; if (hitInfo == null) { Debugger.Break(); return; } var hitPoint = PathRay.Point(rayHit.Distance); //If Hit light) if (hitInfo.IsLight) { var lt = scene.GetLightByIndex(currentTriangleIndex); vertices[currentVertice] = new LightsourcePathElement() { HitInfo = hitInfo, Throughput = this.Throughput, LightSample = new LightSample() { Spectrum = lt.Le(ref PathRay.Dir), Pdf = 1f } }; PathState = GenericPathSamplerState.Evaluation; return; } Vector wo = -PathRay.Dir; float fPdf; Vector wi; float u0 = Sample.GetLazyValue(), u1 = Sample.GetLazyValue(), u2 = Sample.GetLazyValue(); RgbSpectrum f = hitInfo.Material.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, u0, u1, u2, out fPdf, out specularBounce) * hitInfo.Color; vertices[currentVertice] = new GeometryPathElement() { HitInfo = hitInfo, HitPoint = hitPoint, BsdfSample = new BsdfSample() { SampleData = new[] { u0, u1, u2 }, Wi = wi, Pdf = fPdf, Spectrum = f.ToArray(), SpecularBounce = specularBounce } }; if (hitInfo.Material.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]; var ls = new LightSample(); light.EvaluateShadow(ref hitPoint, ref hitInfo.ShadingNormal, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue(), out ls); if (ls.Pdf <= 0f) { continue; } connections[tracedShadowRayCount].Throughput = new RgbSpectrum(ls.Spectrum); connections[tracedShadowRayCount].Pdf = ls.Pdf; connections[tracedShadowRayCount].Ray = ls.LightRay; Vector lwi = connections[tracedShadowRayCount].Ray.Dir; connections[tracedShadowRayCount].Throughput *= lightTroughtput * Vector.AbsDot(ref hitInfo.ShadingNormal, ref lwi) * hitInfo.Material.f( ref connections[tracedShadowRayCount].Ray.Dir, ref wo, ref hitInfo.ShadingNormal); if (!connections[tracedShadowRayCount].Throughput.IsBlack()) { connections[tracedShadowRayCount].Pdf *= lightStrategyPdf; tracedShadowRayCount++; } } } if ((fPdf <= 0.0f) || f.IsBlack()) { PathState = GenericPathSamplerState.Connection; 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 { PathState = GenericPathSamplerState.Connection; return; } } PathRay.Org = hitPoint; PathRay.Dir = wi.Normalize(); this.PathState = GenericPathSamplerState.Sampling; #if VERBOSE } catch (Exception ex) { Console.WriteLine("Advance path exception"); Console.WriteLine("Error triangle {0}", currentTriangleIndex); Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } #endif }
public void EvaluatePhoton(IRayEngineScene scen, float u0, float u1, float u2, float u3, float u4, out LightSample result) { result = new LightSample(); var scene = (RayEngineScene)scen; float b0, b1, b2; Point orig; scene.Triangles[triangleIndex].Sample(scene.Vertices, u0, u1, out orig, out b0, out b1, out b2); // Ray direction var sampleN = this.TriangleNormal; Vector dir = MC.UniformSampleSphere(u2, u3); float RdotN = Normal.Dot(ref dir, ref sampleN); if (RdotN < 0f) { dir *= -1f; RdotN = -RdotN; } result.LightRay = new RayData(ref orig, ref dir); result.Pdf = (MathLab.INVTWOPI / area) * 1f / RdotN; result.Spectrum = this.lightSpectra; }
public void EvaluateShadow(Core.Surface.BaseBxdf bsdfSample, float u0, float u1, float u2, ref LightSample result) { #if VERBOSE try { #endif if (result == null) result = new LightSample(); if (true) { var wi = MC.CosineSampleHemisphere(u1, u2); wi = bsdfSample.Frame.ToWorld(ref wi); result.LightRay = new RayData(ref bsdfSample.HitPoint.HitPoint, ref wi, 1e-4f, float.MaxValue); result.Distance = 1e4f; result.Spectrum = Le(ref wi); result.Pdf = wi.z * MathLab.INVPI; //var i = ((RgbSpectrumInfo) result.Spectrum).y(); //result.Pdf *= i; } else { Vector wi = MC.UniformSampleSphere(u0, u1); result.LightRay = new RayData(ref bsdfSample.HitPoint.HitPoint, ref wi, 1e-4f, float.MaxValue); result.Pdf = 1f / (4f * MathLab.M_PI); result.Spectrum = Le(ref wi); //var i = ((RgbSpectrumInfo)result.Spectrum).y(); //result.Pdf *= i; } #if VERBOSE } catch (Exception ex) { Tracer.TraceLine(ex.Message); Tracer.TraceLine(ex.StackTrace); throw; } #endif }