protected override void Update(InputSnapshot snapshot, float elapsedSeconds) { base.Update(snapshot, elapsedSeconds); var frameRate = 1f / ElapsedSecondsBetweenRenders; var tickRate = 1f / elapsedSeconds; var rate = Raytracer.RaysPerFrame * frameRate; var millionRate = rate / 1_000_000; var budget = Stopwatch.Frequency / TargetTicksPerFrame; Window.Title = $"{millionRate:F2} MRays / sec. | {Raytracer.RaysPerFrame / 1_000_000:F2} MRays / Frame | {frameRate:F2} FPS | {tickRate:F2} TPS | {MillisecondsPerLogic:F0}ms / Update | {MillisecondsPerRender:F0}ms / Render | Budget: {budget:F0}ms / Frame"; if (ImGui.Begin("Debug")) { if (ImGui.BeginMenu("Raytracer Debug")) { if (ImGui.Button("Clear Framebuffer")) { Array.Clear(Raytracer.FrameBuffer, 0, Raytracer.FrameBuffer.Length); } ImGui.Checkbox("Render once on button press", ref renderOnce); if (renderOnce && ImGui.Button( renderThread != null && !renderThread.IsCompleted && !renderThread.IsCanceled ? "Rendering" : "Render Once")) { if (renderThread != null && !renderThread.IsCompleted && !renderThread.IsCanceled) { cancellationTokenSource?.Cancel(); } if (renderThread == null || renderThread.IsCompleted || renderThread.IsCanceled) { cancellationTokenSource = new CancellationTokenSource(100); renderThread = Task.Run(Raytracer.RenderCpuNew, cancellationTokenSource.Token); } } } } foreach (var keyEvent in snapshot.KeyEvents) { if (keyEvent.Down && keyEvent.Key == Key.D) { Raytracer.SceneParams.Camera.Origin.X += 1f; Raytracer.SceneParams.Camera.LookAt.X += 1f; Camera.Recalculate(ref Raytracer.SceneParams.Camera); } else if (keyEvent.Down && keyEvent.Key == Key.A) { Raytracer.SceneParams.Camera.Origin.X -= 1f; Raytracer.SceneParams.Camera.LookAt.X -= 1f; Camera.Recalculate(ref Raytracer.SceneParams.Camera); } } Raytracer.RenderSettings(); }