private void DrawInitialDebug(Surface screen) { //Create the surface to draw all the debugging on debugsurface = new Surface(512, 512); //Create a 2D basis based on the camera orientation to project the rays and spheres on DebugYUnit = camera.getDirection(256, 256).direction.Normalized(); Vector3 upesq = camera.getDirection(256, 200).direction.Normalized(); DebugXUnit = (Vector3.Cross(DebugYUnit, upesq)).Normalized(); // draw primitive spheres foreach (Primitive prim in scene.primitives) { if (prim is Sphere) { Sphere s = (Sphere)prim; Vector3 nc = s.center - camera.Position; float nx = Vector3.Dot(DebugXUnit, nc); float ny = Vector3.Dot(DebugYUnit, nc); Vector3 dif = nc - (nx * DebugXUnit + ny * DebugYUnit); float distancesquared = dif.LengthSquared; if (distancesquared > s.radius * s.radius) { continue; // outside the screen. } DrawCircle(debugsurface, TXDebug(nx), TYDebug(ny), (float)Math.Sqrt(s.radius * s.radius - distancesquared), Utils.GetRGBValue(s.material.diffuseColor)); } } // Draw the camera as a point: debugsurface.Plot(TXDebug(0), TYDebug(0), 0xffffff); }
public void Plot(int x, int y, Color3 color, bool gammaCorrection) { if (float.IsNaN(color.R)) { return; } var oldColor = _acc[x, y]; var newColor = (oldColor * NumSamples + color) / (NumSamples + 1); _acc[x, y] = newColor; _screen.Plot(x, y, newColor.ToArgb(gammaCorrection)); }
public void Render(Surface surface) { Stopwatch timer = new Stopwatch(); timer.Start(); // Initial part of Debug screensurface = surface; DrawInitialDebug(surface); // We divide the screen between threads by x-values. // In this fashion: [1, 2, 3, 1, 2, 3, 1, 2, 3, ..., 1, 2 ] // However we begin at the end (Camera.resolution - SpeedUp). int[] startX = new int[nThreads]; for (int i = 0; i < nThreads; i++) { startX[i] = Camera.resolution - (i + 1) * SpeedUp; } // Update draw params: drawParams.SpeedUp = SpeedUp; drawParams.AntiAliasing = AntiAliasing; drawParams.deltaX = nThreads * SpeedUp; drawParams.AAInvSq = 1f / (AntiAliasing * AntiAliasing); drawParams.AAvals = new float[AntiAliasing]; for (int i = 0; i < AntiAliasing; i++) { // Precalculate these variables and put them in an array. drawParams.AAvals[i] = SpeedUp * 0.5f * (1f + 2 * i) / AntiAliasing; } drawParams.surface = surface; Thread[] threads = new Thread[nThreads]; for (int i = 1; i < nThreads; i++) { threads[i] = new Thread(DrawParallel); threads[i].Start(startX[i]); } DrawParallel(startX[0]); // Wait for all OTHER threads until they are done. for (int i = 1; i < nThreads; i++) { threads[i].Join(); } // The debug data is first drawn on a seperate surface, then drawn on the main surface so no debug data is drawn over the main raytracer image int[] debugdata = debugsurface.pixels; for (int x = 0; x < 512; x++) { for (int y = 0; y < 512; y++) { surface.Plot(x + 512, y, debugdata[x + 512 * y]); } } // When we talk about 4x anti-aliasing, we actually mean 2x2 rays instead of 1 per pixel. surface.Print("Anti-Aliasing: " + (AntiAliasing * AntiAliasing), 522, 512 - 48, 0xffffff); surface.Print("Speedup: " + SpeedUp, 522, 512 - 24, 0xffffff); timer.Stop(); Console.WriteLine("One render took " + timer.ElapsedMilliseconds + " ms"); }