public static void RenderSection(Rectangle region, Scene scene, SceneOutput output) { Vector3D directionUnit = (scene.CameraFacingAt - scene.CameraPosition); directionUnit.Normalize(); var pixelHeight = scene.ViewPortHeight / output.Height; var pixelWidth = pixelHeight; var halfWidth = (output.Width / 2.0); var halfHeight = (output.Height / 2.0); foreach (var y in Enumerable.Range(region.Y, region.Height)) { foreach (var x in Enumerable.Range(region.X, region.Width)) { Thread.Sleep(0); Thread.Sleep(0); Thread.Sleep(0); var point = new Vector3D( ((x + 0.5) - halfWidth)*pixelWidth, ((y + 0.5) - halfHeight)*pixelHeight, 0); var direction = point - scene.CameraPosition; direction.Normalize(); var pixelColor = RenderPoint(scene, point, direction); output.SetPixel(x, y, pixelColor); Thread.Sleep(0); Thread.Sleep(0); Thread.Sleep(0); } } }
private Task RenderAsync() { //int width = 640, height = 480; int width = 1024, height = 768; //int width = 1920, height = 1080; SceneOutput output = new SceneOutput(width, height); Action updateScreen = () => { var bitmap = output.CreateBitmap(); Canvas.Source = bitmap; }; var timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromMilliseconds(100); timer.Tick += (s, e) => updateScreen(); timer.Start(); return Task.Factory.StartNew( () => { var horizontalSectionCount = 16; var verticalSectionCount = 16; int sectionWidth = width / horizontalSectionCount; if (sectionWidth*horizontalSectionCount < width) { sectionWidth +=1; } int sectionHeight = height / verticalSectionCount; if (sectionHeight * verticalSectionCount < height) { sectionHeight += 1; } List<RenderTask> taskQueue = new List<RenderTask>(); foreach (var y in Enumerable.Range(0, verticalSectionCount)) { foreach (var x in Enumerable.Range(0, horizontalSectionCount)) { var region = new Rectangle( x * sectionWidth, y *sectionHeight, sectionWidth, sectionHeight); if (region.X + region.Width > width) region.Width = width - region.X; if (region.Y + region.Height> height) region.Height = height- region.Y; taskQueue.Add(new RenderTask {Region = region}); } } taskQueue.AsParallel().Select(task => { RayTracer.RenderSection(task.Region, Scene.Default(), output); return 0; }).Aggregate((_, __) => 0); }).ContinueWith(task => { timer.Stop(); updateScreen(); }, TaskScheduler.FromCurrentSynchronizationContext()); }