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; } } }