我试图运行一个游戏在60 fps而不是30。游戏是锁定到30 fps,所以唯一的方法,我可以达到60 fps是与帧插值。
对于插值部分,我将使用OpenCV,我发现this pretty good article。
这款游戏使用OpenGL。经过一番研究,我发现抓取屏幕的最佳方法是挂钩SwapBuffer函数。所以我选择挂钩游戏抓取屏幕并将其发送到其他应用程序,该应用程序将以真实的时间传输游戏,顺便添加插值帧以达到60 FPS(如果您有更好的想法,我完全开放!)
我开始写我的新DLL。我用C#编码,我选择了EasyHook来注入我的DLL。
Hooking工作得很好,现在很酷=D。
然而,我现在卡住了,因为我完全不知道如何从游戏中抓取屏幕。
我尝试使用OpenGL.Net和SharpGL,但我不知道如何获取实际的OpenGL上下文来使用glReadPixel!
下面是我的实际代码:
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);
}
}
}
字符串
1条答案
按热度按时间np8igboo1#
我怀疑你能提高游戏的FPS。顺便说一下,有一些可能性。
你所做的是正确的方法,你只是错过了GL代码来创建要显示的中间框架(我建议使用当前GL上下文在进程中创建它)。
问题是当
SwapBuffers
命令被执行时,视频帧被显示出来。这是你挂起的命令,但是问问你自己和程序:为什么SwapBuffers
每秒被调用30次?如果答案是“因为应用程序使用计时器挂起执行”,那么您就不能简单地解决这个问题:您的钩子必须与应用程序一起工作,因此您需要了解应用程序是如何休眠的。
如果答案是“Because the application is taking advantage of WGL_EXT_swap_control”,那么你有一种可能性:
如何创建插值帧?如果你是通过CPU做的,使用glReadPixels和后台缓冲区(GL_BACK)作为读帧缓冲区(使用glDrawBuffers)。这将下载帧缓冲区绑定的内容。然后使用混合方程获得插值像素。