2017-05-09 26 views
2

30 대신 60Fps로 게임을 실행하려고합니다. 게임은 30fps로 고정되어 있으므로 60fps에 도달 할 수있는 유일한 방법은 프레임 보간입니다.C# Opengl Hook 스왑 버퍼 보간 프레임 추가

보간 부분은 OpenCV를 사용하려고합니다. this pretty good article입니다.

이 게임은 OpenGL을 사용합니다. 몇 가지 조사를 한 후에, 나는 화면을 잡는 가장 좋은 방법은 SwapBuffer 함수를 연결하는 것이라고 발견했다. 그래서 게임을 연결하여 화면을 잡고 다른 앱으로 보내면 실시간으로 게임을 스트리밍하고 60 fps에 도달하는 보간 프레임을 추가합니다 (더 좋은 아이디어가 있다면 완전히 open!)

나는 새 DLL을 작성하기 시작했다. 저는 C#으로 코딩하고 있으며, EasyHook을 선택하여 DLL을 주입했습니다.

후킹이 잘 작동하고 있으며, 지금은 매우 멋지다. = D.

그러나 게임에서 화면을 잡는 방법을 전혀 알지 못해서 지금은 막혀 있습니다.

OpenGL.NetSharpGL을 사용해 보았지만 실제 OpenGL 컨텍스트를 잡아 glReadPixel을 사용한다고 가정합니다. 난 당신이 게임의 FPS를 증가시킬 수 있습니다 의심

using System; 
using System.Runtime.InteropServices; 


namespace Hook 
{ 
    public class ServerInterface : MarshalByRefObject 
    { 
     public void IsInstalled(int clientPID) 
     { 
      Console.WriteLine("This programm has injected dll into process {0}.\r\n", clientPID); 
     } 

     public void ReportMessage(int clientPID, string message) 
     { 
      Console.WriteLine(message); 
     } 

     public void ReportException(Exception e) 
     { 
      Console.WriteLine("The target process has reported an error:\r\n" + e.ToString()); 
     } 

     public void Ping() 
     { 
      Console.WriteLine("Ping !"); 
     } 
    } 


    //Point d'entrée 
    public class InjectionEntryPoint : EasyHook.IEntryPoint 
    { 
     //Serveur : 
     ServerInterface server = null; 

     public InjectionEntryPoint(EasyHook.RemoteHooking.IContext context, string channelName) 
     { 
      //Constructeur 
      //Objectif : vérifier si la communication entre les deux programmes peut etre établit 
      server = EasyHook.RemoteHooking.IpcConnectClient<ServerInterface>(channelName); 
      server.Ping(); 

     } 

     public void Run(EasyHook.RemoteHooking.IContext context, string channelName) 
     { 

      try 
      { 
       var SwapBuffersHook = EasyHook.LocalHook.Create(EasyHook.LocalHook.GetProcAddress("opengl32.dll", "wglSwapBuffers"), new SwapBuffers_Delegate(SwapBuffers_Hook), this); 
       SwapBuffersHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 }); 
       server.ReportMessage(EasyHook.RemoteHooking.GetCurrentProcessId(), "SwapBuffers Hooked"); 
      } 
      catch (Exception ExtInfo) 
      { 
       server.ReportException(ExtInfo); 
       return; 
      } 

      server.IsInstalled(EasyHook.RemoteHooking.GetCurrentProcessId()); 

      EasyHook.RemoteHooking.WakeUpProcess(); 

      //Waiting years 
      while(true) 
      { 
       System.Threading.Thread.Sleep(10000); 
      } 


      // Finalise cleanup of hooks 
      EasyHook.LocalHook.Release(); 

     } 


     //Deleguate 
     [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] 
     delegate IntPtr SwapBuffers_Delegate(IntPtr hdc); 

     //Original 
     [DllImport("opengl32.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)] 
     static extern IntPtr wglSwapBuffers(IntPtr hdc); 

     //Hook function 
     public IntPtr SwapBuffers_Hook(IntPtr hdc) 
     { 

      server.ReportMessage(EasyHook.RemoteHooking.GetCurrentProcessId(), "I'm in SwapBuffers =DDDD"); 

      //Here I need to grab frames 

      //Return 
      return wglSwapBuffers(hdc); 
     } 
    } 
} 
+0

컨텍스트 생성 프로세스에 연결하여 정보를 저장할 수도 있습니다. 그러나 이미 버퍼 스와핑 프로세스에 연결하고 있으므로 올바른 OpenGL 컨텍스트가 이미 버퍼 스왑을 실행하는 스레드에 바인딩되어 있지 않아야합니까? – BDL

답변

0

:

여기 내 실제 코드입니다. 그건 그렇고, 몇 가지 가능성이 있습니다.

무엇을하고 계십니까? GL 코드가 표시되어 중간 프레임을 만들지 못하게됩니다 (현재 GL 컨텍스트를 사용하여 프로세스 내에서 만들 것을 제안합니다).

SwapBuffers 명령을 실행하면 비디오 프레임이 표시되는 것이 문제입니다. 이것은 당신이 후크이지만, 자신과 프로그램에 질문하십시오 : SwapBuffers이 초당 30 번 호출되는 이유는 무엇입니까?

"응용 프로그램이 타이머를 사용하여 실행을 일시 중지하기 때문에"쉽게 해결할 수 없습니다. 즉, 응용 프로그램과 함께 작동해야하므로 응용 프로그램의 작동 상태를 이해해야합니다.

answe 인 경우 하나 가능성 것보다, "응용 프로그램이 WGL_EXT_swap_control을 활용하기 때문에"응용 프로그램이 wglSwapIntervalEXT라고 때문에

  • 설정 wglSwapIntervalEXT (1) ((2) (30)를 얻을 수를 FPS가 V-Sync와 동기화되었습니다. 아마도 한 번만 필요합니다.
  • 후크에서 두 프레임을 잡고 모든 다른 프레임에서 질문을 삽입합니다. 따라서 각 후크 실행시 보간 된 프레임을 렌더링해야합니다. 그 다음 스왑 한 다음 다음 원본 프레임을 렌더링 한 다음 교환하십시오.

보간 프레임을 만드는 방법은 무엇입니까? CPU를 통해 작업하는 경우 백 버퍼 (GL_BACK)와 함께 glReadPixels을 읽기 프레임 버퍼 (glDrawBuffers 사용)로 사용하십시오. 이것은 바운드 된 프레임 버퍼의 내용을 다운로드 할 것입니다. 그런 다음 블렌딩 방정식을 사용하여 보간 된 픽셀을 얻습니다.