// Update the texture with a portion of the given film. public void UpdateTileFromFilm(Bounds2 <int> tileBounds, Film film) { foreach (var posFilm in tileBounds.IteratePoints()) { if (posFilm.X >= 0 && posFilm.X < Program.Width && posFilm.Y >= 0 && posFilm.Y < Program.Height) { var pixel = film.GetPixel(posFilm); var color = pixel.contribSum / pixel.filterWeightSum; var offset = (posFilm.Y * Width + posFilm.X) * 4; // BGRA bitmap[offset + 0] = (byte)Math.Min(255, color.B * 255); bitmap[offset + 1] = (byte)Math.Min(255, color.G * 255); bitmap[offset + 2] = (byte)Math.Min(255, color.R * 255); } } }
public override void Render(Scene scene, Camera camera, IWindow window) { Preprocess(scene); // Compute the number of tiles to use var sampleBounds = camera.Film.GetSampleBounds(); var sampleExtent = sampleBounds.Diagonal(); var nTiles = new Vector2 <int>( (sampleExtent.X + Program.TileSize - 1) / Program.TileSize, (sampleExtent.Y + Program.TileSize - 1) / Program.TileSize); // Render tiles in parallel //Parallel.For(0, nTiles.X * nTiles.Y, tile => Parallel.For(0, nTiles.X * nTiles.Y, new ParallelOptions { MaxDegreeOfParallelism = Program.ThreadCount }, tile => { var tileX = tile % nTiles.X; var tileY = tile / nTiles.X; // Get a sampler instance for the current tile var seed = tileY * nTiles.X + tileX; var tileSampler = Sampler.Clone(seed); // Compute the extent of pixels to be sampled in this tile var x0 = sampleBounds.Min.X + tileX * Program.TileSize; var x1 = Math.Min(x0 + Program.TileSize, sampleBounds.Max.X); var y0 = sampleBounds.Min.Y + tileY * Program.TileSize; var y1 = Math.Min(y0 + Program.TileSize, sampleBounds.Max.Y); var tileBounds = new Bounds2 <int>(new Point2 <int>(x0, y0), new Point2 <int>(x1, y1)); var filmTile = camera.Film.GetTile(tileBounds); MarkTile(tileBounds); // Loop over the pixels in the tile foreach (var pixel in tileBounds.IteratePoints()) { tileSampler.StartPixel(pixel); do { var cameraSample = tileSampler.GetCameraSample(pixel); if (pixel.X == 48 && pixel.Y == 209) { } // Generate a camera ray for the current sample var rayWeight = camera.GenerateRayDifferential(cameraSample, out RayDifferential ray); ray.ScaleDifferentials((float)(1.0f / Math.Sqrt(tileSampler.SamplesPerPixel))); // Evaluate radiance along the camera ray var L = Spectrum.Zero; if (rayWeight > 0) { L = Li(ray, scene, camera, tileSampler); } // TODO check invalid radiance // Add the ray's contribution to the image filmTile.AddSample(cameraSample.PosFilm, L, rayWeight); } while (tileSampler.StartNextSample()); } // Merge the tile into the film camera.Film.MergeTile(filmTile); //Thread.Sleep(100); UnmarkTile(tileBounds); UpdateTileFromFilm(tileBounds, camera.Film); }); }