public WavelengthCluster Mul(WavelengthCluster c) { if ((Math.Abs(c.LambdaStart - LambdaStart) > MathLab.Epsilon) || (c.Values.Length != Values.Length)) { return this; } for (int i = 0; i < Values.Length; i++) { Values[i] = Values[i] * c.Values[i]; } return this; }
public override void RenderPass() { var sb = film.GetFreeSampleBuffer(); var sw = Stopwatch.StartNew(); var samplesPerPass = Scene.w * Scene.h; float dLambda = (SampledSpectrum.sampledLambdaEnd - SampledSpectrum.sampledLambdaStart) / ((float)MaxSpectralSamples + 1f); for (int y = 0; y < Scene.h; ++y) { int pj = 0; for (int x = 0; x < Scene.w; ++x, ++pj) { var cluster = new WavelengthCluster(SampledSpectrum.sampledLambdaStart, dLambda, MaxSpectralSamples); //var c = new WlCluster(MaxSpectralSamples); //for (int l = 0; l < MaxSpectralSamples / SamplesPerCluster; l++) { float[] lambdas = Enumerable.Range(0, MaxSpectralSamples).Select(i => SampleWavelength(rnd.NextFloat())).OrderBy(i=>i).ToArray(); RayData cameraRay; Scene.GenerateCameraRay(x, y, out cameraRay); cluster = EvalRadiance(ref cameraRay, cluster, 0); totalSamples += MaxSpectralSamples; } //cluster.Sort(); IrregularSPD spd = new IrregularSPD(cluster.Lambdas, cluster.Values, MaxSpectralSamples, dLambda); //RegularSPD spd = new RegularSPD(vals, SampledSpectrum.sampledLambdaStart, SampledSpectrum.sampledLambdaEnd, MaxSpectralSamples); var pixV = spd.ToRgb(); sb.SplatSample(x, (Scene.h - y - 1), ref pixV); if (sb.IsFull()) { film.SplatSampleBuffer(true, sb); sb = film.GetFreeSampleBuffer(); } } } pass++; sw.Stop(); stats = string.Format("MSamples per sec {1:F5}; Total Samples {0}; Samples per pixel {2}; {3}", totalSamples, 0.000001 * (samplesPerPass / sw.Elapsed.TotalSeconds), pass, film.GetStats()); }
private WavelengthCluster EvalRadiance(ref RayData r, WavelengthCluster lambdas, int depth) { double t = 0; // distance to intersection int id = 0; // id of intersected object if (!Scene.Intersect(ref r, ref t, ref id) || depth > MaxDepth) { return black; } var obj = SceneManager.Sph[id]; var x = r.Point((float)t); Normal n = (Normal)(x - obj.p).Normalize(); var nl = Vector.Dot(ref n, ref r.Dir) < 0 ? n : n * -1; RayData newRay = new RayData(); float[] fs = new float[MaxSpectralSamples]; depth++; for (int i = 0; i < MaxSpectralSamples; i++) { var lambda = lambdas.Lambdas[i]; var f = obj.c.Sample(lambda); var e = 0f; var p = f; if (obj.refl == 3) { e += f; } if (depth > MaxDepth) { if (rnd.NextFloat() < p) { f = f * (1f / p); } else { fs[i] = e; } } var brdf = Brdfs[obj.refl]; Vector dir; float fb; brdf.Sample(ref r.Dir, ref n, rnd.NextFloat(), rnd.NextFloat(), lambda, out dir, out fb); newRay = new RayData(ref x, ref dir); fs[i] = e + f * fb; } lambdas.Add(new WavelengthCluster(lambdas.Lambdas, fs)); return lambdas.Mul(EvalRadiance(ref newRay, lambdas, depth)); }