void OnGUI() { if (guiSkin) { GUI.skin = guiSkin; } if (!rtex_equi) { Debug.LogError("No texture assigned to rtex_equi!"); return; } if (showModelOverlay) { //RenderTexture.active = rtex_equi; //GUI.DrawTexture(new Rect(10,10,360,180), rtex_equi, ScaleMode.ScaleToFit, false, 0); GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), rtex_equi, ScaleMode.StretchToFill); if (bGuiVisible && cubemapToProjectionMaterial) { selectionGridInt = GUI.SelectionGrid(new Rect(20, 10, 200, 160), selectionGridInt, LensModelNames, 1); if (selectionGridInt != prevSelectionGridInt) { // select our new lens model mLensmodel.setProjection((LensModel.LENSMODEL)selectionGridInt); cubemapToProjectionMaterial.DisableKeyword("LM_" + LensModel.lensModelNames[prevSelectionGridInt]); cubemapToProjectionMaterial.EnableKeyword("LM_" + LensModel.lensModelNames[selectionGridInt]); // if LM_CYLINDRICAL, we have to update hradpermm uniform cubemapToProjectionMaterial.SetFloat("hradpermm", (float)mLensmodel.getHradPerMm()); // save it in system selectedModel = LensModel.lensModelNames[selectionGridInt]; selectedModelID = (LensModel.LENSMODEL)selectionGridInt; prevSelectionGridInt = selectionGridInt; fov = 90; UpdateFOV(); } if (GUI.Button(new Rect(20, 190, 100, 20), "RESET")) { Debug.Log("ArcBall Reset"); mArcball.reset(); this.transform.rotation = mArcball.getRotation(); } GUI.Label(new Rect(Screen.width - 200, 10, 200, 40), selectedModel + "\nFOV: " + fov.ToString()); GUI.Label(new Rect(Screen.width - 200, 40, 200, 40), "FPS: " + mFps.GetFPS().ToString()); } } }
public override void Update() { fps.Update(); var zoom = Input.GetKey(Keyboard.Key.Hyphen) - Input.GetKey(Keyboard.Key.Equal); camZoom += zoom * (0.001f * zoomSpeed); camZoom = Math.Clamp(camZoom, 0.1f, 0.28f); if (Input.GetKeyDown(Keyboard.Key.Backspace, true)) { camZoom = 0.2f; } cameraView.Center = new Vector2f(target.X, target.Y); var x = (float)Math.Floor(target.X); var y = (float)Math.Floor(target.Y + 15); var fpsText = $"FPS: {fps.GetFPS()}\n"; var position = $"X: {x}, Y: {y}\n"; hudText.DisplayedString = fpsText + position; }
/// <summary> /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling /// (anti-aliasing) /// </summary> /// <param name="swapChainPtr"></param> /// <param name="syncInterval"></param> /// <param name="flags"></param> /// <returns>The HRESULT of the original method</returns> private int PresentHook(IntPtr swapChainPtr, int syncInterval, PresentFlags flags) { Frame(); var swapChain = (SwapChain)swapChainPtr; try { #region Screenshot Request if (Request != null) { try { DebugMessage("PresentHook: Request Start"); var startTime = DateTime.Now; using (var texture = Resource.FromSwapChain <Texture2D>(swapChain, 0)) { #region Determine region to capture var regionToCapture = new Rectangle(0, 0, texture.Description.Width, texture.Description.Height); if (Request.RegionToCapture.Width > 0) { regionToCapture = Request.RegionToCapture; } #endregion var theTexture = texture; // If texture is multisampled, then we can use ResolveSubresource to copy it into a non-multisampled texture Texture2D textureResolved = null; if (texture.Description.SampleDescription.Count > 1) { DebugMessage("PresentHook: resolving multi-sampled texture"); // texture is multi-sampled, lets resolve it down to single sample textureResolved = new Texture2D(texture.Device, new Texture2DDescription { CpuAccessFlags = CpuAccessFlags.None, Format = texture.Description.Format, Height = texture.Description.Height, Usage = ResourceUsage.Default, Width = texture.Description.Width, ArraySize = 1, SampleDescription = new SampleDescription(1, 0), // Ensure single sample BindFlags = BindFlags.None, MipLevels = 1, OptionFlags = texture.Description.OptionFlags }); // Resolve into textureResolved texture.Device.ResolveSubresource(texture, 0, textureResolved, 0, texture.Description.Format); // Make "theTexture" be the resolved texture theTexture = textureResolved; } // Create destination texture var textureDest = new Texture2D(texture.Device, new Texture2DDescription { CpuAccessFlags = CpuAccessFlags.None, // CpuAccessFlags.Write | CpuAccessFlags.Read, Format = Format.R8G8B8A8_UNorm, // Supports BMP/PNG Height = regionToCapture.Height, Usage = ResourceUsage.Default, // ResourceUsage.Staging, Width = regionToCapture.Width, ArraySize = 1, //texture.Description.ArraySize, SampleDescription = new SampleDescription(1, 0), // texture.Description.SampleDescription, BindFlags = BindFlags.None, MipLevels = 1, //texture.Description.MipLevels, OptionFlags = texture.Description.OptionFlags }); // Copy the subresource region, we are dealing with a flat 2D texture with no MipMapping, so 0 is the subresource index theTexture.Device.CopySubresourceRegion(theTexture, 0, new ResourceRegion { Top = regionToCapture.Top, Bottom = regionToCapture.Bottom, Left = regionToCapture.Left, Right = regionToCapture.Right, Front = 0, Back = 1 // Must be 1 or only black will be copied }, textureDest, 0, 0, 0, 0); // Note: it would be possible to capture multiple frames and process them in a background thread // Copy to memory and send back to host process on a background thread so that we do not cause any delay in the rendering pipeline var request = Request.Clone(); // this.Request gets set to null, so copy the Request for use in the thread ThreadPool.QueueUserWorkItem(delegate { //FileStream fs = new FileStream(@"c:\temp\temp.bmp", FileMode.Create); //Texture2D.ToStream(testSubResourceCopy, ImageFileFormat.Bmp, fs); var startCopyToSystemMemory = DateTime.Now; using (var ms = new MemoryStream()) { Resource.ToStream(textureDest, ImageFileFormat.Bmp, ms); ms.Position = 0; this.DebugMessage("PresentHook: Copy to System Memory time: " + (DateTime.Now - startCopyToSystemMemory)); var startSendResponse = DateTime.Now; ProcessCapture(ms, request); this.DebugMessage("PresentHook: Send response time: " + (DateTime.Now - startSendResponse)); } // Free the textureDest as we no longer need it. textureDest.Dispose(); textureDest = null; this.DebugMessage("PresentHook: Full Capture time: " + (DateTime.Now - startTime)); }); // Make sure we free up the resolved texture if it was created if (textureResolved != null) { textureResolved.Dispose(); textureResolved = null; } } DebugMessage("PresentHook: Copy BackBuffer time: " + (DateTime.Now - startTime)); DebugMessage("PresentHook: Request End"); } finally { // Prevent the request from being processed a second time Request = null; } } #endregion #region Example: Draw overlay (after screenshot so we don't capture overlay as well) if (Config.ShowOverlay) { using (var texture = Resource.FromSwapChain <Texture2D>(swapChain, 0)) { if (FPS.GetFPS() >= 1) { var fd = new FontDescription { Height = 16, FaceName = "Arial", Italic = false, Width = 0, MipLevels = 1, CharacterSet = FontCharacterSet.Default, OutputPrecision = FontPrecision.Default, Quality = FontQuality.Antialiased, PitchAndFamily = FontPitchAndFamily.Default | FontPitchAndFamily.DontCare, Weight = FontWeight.Bold }; // TODO: Font should not be created every frame! using (var font = new Font(texture.Device, fd)) { DrawText(font, new Vector2(5, 5), string.Format("{0:N0} fps", FPS.GetFPS()), new Color4(Color.Red.ToColor3())); if (TextDisplay != null && TextDisplay.Display) { DrawText(font, new Vector2(5, 25), TextDisplay.Text, new Color4(Color.Red.ToColor3(), (Math.Abs(1.0f - TextDisplay.Remaining)))); } } } } } #endregion } catch (Exception e) { // If there is an error we do not want to crash the hooked application, so swallow the exception DebugMessage("PresentHook: Exeception: " + e.GetType().FullName + ": " + e.Message); } // As always we need to call the original method, note that EasyHook has already repatched the original method // so calling it here will not cause an endless recursion to this function swapChain.Present(syncInterval, flags); return(Result.Ok.Code); }
/// <summary> /// Implementation of capturing from the render target of the Direct3D9 Device (or DeviceEx) /// </summary> /// <param name="device"></param> private void DoCaptureRenderTarget(Device device, string hook) { FPS.Frame(); if (CaptureThisFrame) #region CompasRenderLoop { try { if (imGuiRender == null && device != null && device.NativePointer != IntPtr.Zero) { Trace.Write("Creating ImGui"); var handle = CurrentProcess.MainWindowHandle; var rect = new NativeMethods.Rect(); NativeMethods.GetWindowRect(handle, ref rect); _sprite = ToDispose(new Sprite(device)); IntialiseElementResources(device); imGuiRender = ToDispose(new ImGuiRender(device, rect, Interface, CurrentProcess)); } else if (imGuiRender != null) { if (Services.CompassSettings.ShowRenderTime) { PerfomanseTester.Reset(); PerfomanseTester.Start(); } else if (PerfomanseTester.IsRunning) { PerfomanseTester.Stop(); } _sprite.Begin(SpriteFlags.AlphaBlend); imGuiRender.GetNewFrame(); var CompassViewModel = PacketProcessor.Instance?.CompassViewModel; CompassViewModel?.Render(_sprite); //ImGui.ShowDemoWindow(); if (Services.CompassSettings.ShowRenderTime) { var draw_list = ImGui.GetOverlayDrawList(); draw_list.AddText(new Vector2(10, 100), $"RenderingTime(ms) = {Elapsed.Milliseconds}", Color.Red.ToDx9ARGB()); draw_list.AddText(new Vector2(10, 50), DateTime.Now.ToString("HH: mm:ss.fff"), Color.White.ToDx9ARGB()); } if (Services.CompassSettings.ShowFPS) { ImGui.SetNextWindowBgAlpha(0); if (ImGui.Begin("FPS counter", ref Services.CompassSettings._showFps, ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.AlwaysAutoResize)) { ImGui.SetWindowFontScale(1.3F); ImGui.Text($"{FPS.GetFPS():n0} fps"); } ImGui.End(); } _sprite.End(); imGuiRender.Draw(); if (Services.CompassSettings.ShowRenderTime && PerfomanseTester.IsRunning) { PerfomanseTester.Stop(); Elapsed = PerfomanseTester.Elapsed; } } } catch (Exception e) { DebugMessage(e.ToString()); _sprite.End(); } } #endregion }