gpt4 book ai didi

C# Opengl Hook Swapbuffer 添加插值帧

转载 作者:太空宇宙 更新时间:2023-11-03 15:05:16 31 4
gpt4 key购买 nike

我正在尝试以 60Fps 而不是 30Fps 运行游戏。游戏锁定为 30fps,因此我可以达到 60fps 的唯一方法是帧插值。

对于插值部分,我将使用 OpenCV,我找到了 this pretty good article .

此游戏使用 OpenGL。经过一番研究,我发现最好的抓屏方式是hook SwapBuffer函数。所以我选择 Hook 游戏来抓取屏幕并将它们发送到另一个应用程序,这将实时播放游戏并顺便添加插值帧以达到 60 FPS(如果你有更好的主意,我完全打开!)

我开始编写我的新 dll。我使用 C# 编写代码,并选择 EasyHook 来注入(inject)我的 DLL。

Hooking 运行良好,现在非常酷 =D。

但是,我现在卡住了,因为我完全不知道如何从游戏中抓取屏幕。

我尝试使用 OpenGL.NetSharpGL ,但我无法弄清楚我应该如何获取实际的 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);
}
}
}

最佳答案

我怀疑您能否提高游戏的 FPS。顺便说一句,有一些可能性。

你在做什么是正确的方法。您只是错过了创建要显示的中间框架的 GL 代码(我建议使用当前的 GL 上下文在进程中创建它)。

问题是在执行 SwapBuffers 命令时显示视频帧。这是您 Hook 的那个,但问问自己和程序:为什么每秒调用 30 次 SwapBuffers

如果答案是“因为应用程序使用定时器挂起执行”,你就不能轻易解决这个问题:你的钩子(Hook)必须与应用程序一起工作,因此你需要了解应用程序如何休眠。

如果答案是“因为应用程序正在利用 WGL_EXT_swap_control”,那么您有一种可能性:

  • 设置 wglSwapIntervalEXT(1)(因为应用程序调用了 wglSwapIntervalEXT(2) 以获得与 V-Sync 同步的 30 FPS。可能这只需要一次
  • 在你的钩子(Hook)中,抓取两帧,然后在每隔一帧对它们进行插值(因此你的问题)。在每个钩子(Hook)执行时,您需要渲染插值帧,然后交换;然后渲染下一个原始帧,然后交换。

如何创建插值帧?如果您通过 CPU 进行操作,请将 glReadPixels 与后台缓冲区 (GL_BACK) 一起用作读取帧缓冲区(使用 glDrawBuffers)。这将下载帧缓冲区绑定(bind)的内容。然后使用混合方程得到插值像素。

关于C# Opengl Hook Swapbuffer 添加插值帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43877395/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com