Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#Opengl钩子Swapbuffer添加插值帧_C#_Opengl_Hook_Screenshot_Interpolation - Fatal编程技术网

C#Opengl钩子Swapbuffer添加插值帧

C#Opengl钩子Swapbuffer添加插值帧,c#,opengl,hook,screenshot,interpolation,C#,Opengl,Hook,Screenshot,Interpolation,我试着以60帧而不是30帧的速度运行游戏。游戏锁定为每秒30帧,所以我唯一能达到每秒60帧的方法就是使用帧插值 对于插值部分,我将使用OpenCV,我发现 这个游戏使用OpenGL。经过一些研究,我发现抓取屏幕的最好方法是钩住SwapBuffer函数。因此,我选择挂接游戏以抓取屏幕并将其发送到另一个应用程序,该应用程序将实时播放游戏,顺便说一句,将添加插值帧以达到60 FPS(如果你有更好的想法,我完全开放!) 我开始写我的新dll。我正在用C#编写代码,我选择EasyHook注入我的DLL 钩

我试着以60帧而不是30帧的速度运行游戏。游戏锁定为每秒30帧,所以我唯一能达到每秒60帧的方法就是使用帧插值

对于插值部分,我将使用OpenCV,我发现

这个游戏使用OpenGL。经过一些研究,我发现抓取屏幕的最好方法是钩住SwapBuffer函数。因此,我选择挂接游戏以抓取屏幕并将其发送到另一个应用程序,该应用程序将实时播放游戏,顺便说一句,将添加插值帧以达到60 FPS(如果你有更好的想法,我完全开放!)

我开始写我的新dll。我正在用C#编写代码,我选择EasyHook注入我的DLL

钩子很好用,现在很酷

然而,我现在陷入了困境,因为我完全不知道如何从游戏中抓取屏幕

我试图使用和,但我不知道我应该如何抓住实际的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);
        }
    }
}
使用系统;
使用System.Runtime.InteropServices;
名称空间挂钩
{
公共类服务器接口:MarshalByRefObject
{
已安装public void(int clientPID)
{
WriteLine(“此程序已将dll注入进程{0}.\r\n”,clientPID);
}
公共void报告消息(int clientPID,字符串消息)
{
控制台写入线(消息);
}
公共无效报告例外(例外e)
{
Console.WriteLine(“目标进程报告了一个错误:\r\n”+e.ToString());
}
公开作废
{
控制台。WriteLine(“Ping!”);
}
}
//恩特雷角酒店
公共类InjectionEntryPoint:EasyHook.IEntryPoint
{
//服务员:
服务器接口服务器=null;
公共InjectionEntryPoint(EasyHook.RemoteHooking.IContext上下文,字符串channelName)
{
//建设者
//目标:为实现这一目标而进行的双向交流项目
server=EasyHook.RemoteHooking.IpcConnectClient(channelName);
Ping();
}
公共无效运行(EasyHook.RemoteHooking.IContext上下文,字符串channelName)
{
尝试
{
var swapbuffershake=EasyHook.LocalHook.Create(EasyHook.LocalHook.GetProcAddress(“opengl32.dll”,“wglSwapBuffers”),新的SwapBuffers_委托(SwapBuffers_Hook),这是);
swapBuffershake.ThreadACL.SetExclusiveACL(新的Int32[]{0});
ReportMessage(EasyHook.RemoteHooking.GetCurrentProcessId(),“SwapBuffers Hooked”);
}
捕获(例外情况)
{
server.ReportException(exemefo);
返回;
}
已安装server.IsInstalled(EasyHook.RemoteHooking.GetCurrentProcessId());
EasyHook.RemoteHooking.WakeUpProcess();
//等待年
while(true)
{
系统线程线程睡眠(10000);
}
//完成吊钩的清理工作
EasyHook.LocalHook.Release();
}
//消除
[非托管函数指针(CallingConvention.StdCall,CharSet=CharSet.Unicode,SetLastError=true)]
IntPtr SwapBuffers_代表(IntPtr hdc);
//原创的
[DllImport(“opengl32.dll”,CharSet=CharSet.Unicode,SetLastError=true,CallingConvention=CallingConvention.StdCall)]
静态外部IntPtr wglSwapBuffers(IntPtr hdc);
//钩子函数
公共IntPtr SwapBuffers_Hook(IntPtr hdc)
{
ReportMessage(EasyHook.RemoteHooking.GetCurrentProcessId(),“我在SwapBuffers=ddddd中”);
//这里我需要抓取框架
//返回
返回wglSwapBuffers(hdc);
}
}
}

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

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

问题是执行
SwapBuffers
命令时会显示视频帧。这就是你钩住的一个,但是问问你自己和程序:为什么
SwapBuffers
每秒被调用30次

如果答案是“因为应用程序使用计时器暂停执行”,那么您无法轻松解决它:钩子必须与应用程序一起工作,因此您需要了解应用程序是如何休眠的

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

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

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

您也可以连接到上下文创建过程并存储信息。但是,既然您已经连接到缓冲区交换过程,那么正确的OpenGL上下文不应该已经绑定到执行此操作的线程中吗他在交换缓冲区?