Reshade插件(add-ons)介绍及文档翻译

随便搜了一下没发现这类型的文章,刚好也要用到这个功能,于是就做了。

本文介绍了Reshade这个大家常用工具的一个不怎么有人用,但又特别强大的功能特性:add-ons(在这里我翻译为插件)。含个人见解,如和您的理解不同,请积极提出,我一定乐于接受并改正。阅读本文你需要:

  1. 一定的C++基础

  2. 一定的图形API基础

  3. 熟悉Reshade本体的各种操作

    本文主要以辐射4、Reshade 5.4.2、DX11为例子,但Reshade自然是支持各种图形API和游戏的,因此其他游戏也可以参照此介绍。但要注意的是:Reshade插件不能用在任何网络游戏或者会检测作弊的游戏上面,其独特的实现方式会直接触发反作弊机制!!!

1、什么是Reshade插件

    可能有有经验的小伙伴立马就跳出来回答了:我知道!就是平时在游戏中用的那个DLL,能够开启很多特效来增强画质。这里我就要对此进行一点点的区分。首先要知道的是,我们平时用的Reshade可以分为三个部分:

  1. Reshade.dll:其提供了一个基本框架以加载并管理特效(effect)的使用,以及可视化的界面以供用户操作。

  2. 特效(Effects):以HLSL, GLSL or SPIR-V等语言编写的特效,他们规定了屏幕上面的像素将要怎么变化。

  3. 插件(Add-ons):利用高级语言编写CPU指令的方式,调用Reshade抽象并包装好的函数。能够对所使用的资源以及特效进行管理。用人话来说,就是能让这些特效不再是无条件出现,可以让它在合适的时间出现在合适的地方。同时也能去操作图形API的底层逻辑,实现很多骚操作。

    至此,相信各位也能看出来这三者的区别,也对本次要介绍的主要对象有个大致的了解。

2、为什么要使用Reshade插件

    除了刚才说到的:“方便管理和调度以外”。使用Reshade插件的另一好处就是高效,在观察了一些作者制作的特效之后,我发现作者们为了兼容Reshade的各种开关,写出来的特效文件或多或少都带了一些条件分支(也就是if…else…语言)。但由于CPU和GPU的不同,(且特效文件一般由GPU去执行),这些条件分支对于GPU性能的影响特别大,而通过插件的方式能够避免这种情况的发生。

    同时,dll这种动态链接库的方式,也能更好地和游戏插件的代码配合,比如辐射4的F4SE(已经测试过完美兼容)。

    对于我这种苦苦挣扎于整明白图形API,并使用他来做些好玩意儿的人,插件特性的出现无疑是个惊喜。最直观的表现就是我不必再需要和庞大的图形库漫无目的地自由摔跤,一些常用的功能都有人给我包装起来了。

3、怎么使用Reshade插件

    实际上,官方主页上面有Reshade插件的食用方法,因此我这里就在其基础上,翻译过来并添加了一些个人理解。

    以防自己翻译的不准确,这里把自己不太确定的词用图片的方式说明一下:

  1. 覆盖层(OverLays):

 2.图形管线:

英文原文:

a.前言

    ReShade API可以让你与ReShade载入的应用程序的资源和渲染命令进行一个狠狠的操作。 它抽象了ReShade支持的各种图形API(Direct3D 9/10/11/12、OpenGL和Vulkan)之间的差异。总之你只要包含了他的头文件,写出来的插件就可以随便用在不同的图形API里面。

    ReShade插件本质来说就是个DLL,它使用仅有头文件的ReShade API来注册回调事件,然后在这些回调被ReShade调用后搞大事情。没有其他更多花里胡哨的东西,不需要导出任何函数,也不需要针对任何库进行链接。只需将ReShade资源库中的include目录添加到你的DLL项目中,并包含reshade.hpp头文件即可愉快食用。

b.基本例子

    下面是一个非常基本的代码例子,这个插件注册了一个回调,每次有帧被Present之后就会执行。

    欢呼吧,到这里你已经写好了一个基本的没啥卵用的Reshade插件

    建立一个插件DLL之后,将其文件扩展名从.dll改为.addon,并将其放入与ReShade相同的目录。下次启动游戏的时候他就会被自动读取。

    其他更复杂的例子可以去看Github上面的example

c.覆盖层

    Reshade也支持添加覆盖层,比如说,它可以用来显示调试信息,或者用来让用户在应用中进行互动。覆盖层是通过使用Dear ImGui 1.86版本来创建的。

    用法自然是先包含imgui.h,然后再包含reshade.hpp,之后ReShade就会自动覆盖Dear ImGui的函数。搞完之后正常使用Dear ImGui(无需构建其源代码文件)即可。

    要注意的是:不要在回调中调用ImGui::Begin和ImGui::End来创建覆盖窗口本身(这两兄弟是正常玩ImGui要用到的),ReShade已经在调用回调函数前后帮你把事办好了。

    然而你是可以用不同的标题调用ImGui::Begin和ImGui::End来打开额外的弹出窗口(不过不建议这样做,因为这些窗口在VR中会整得很复杂)。

    覆盖层的名字在ReShade和所有插件之间是共享的,这意味着你可以用一个已经被ReShade或其他插件使用的名称来注册,从而将小部件附加到他们的覆盖层上。

    例如,reshade::register_overlay(“Settings”, …)允许你在ReShade的设置页面上添加部件,而reshade::register_overlay(“OSD”, …)允许你为ReShade提供的始终可见的屏幕显示(时钟、FPS、帧时间)添加额外信息。

d. 抽象

    图形API的抽象是以Direct3D 12和Vulkan API为基底的,因此,对于以前使用过这些API的开发者来说,许多术语理应比较熟悉。

    所有类和方法的详细文档可以在相关的头文件中找到(关于抽象对象类,请看reshade_api_device.hpp,关于可用事件,请看reshade_events.hpp)。

    其他所有的基础对象都是由reshade::api::device创建的。它代表了一个逻辑上的渲染设备,通常被映射到一个物理GPU(但也可能被映射到多个GPU)。ReShade会在应用程序创建设备后调用reshade::addon_event::init_device事件,它可以用来做一些只需要用到一次的初始化工作。而reshade::addon_event::destroy_device事件会在这个设备再次被销毁之前被调用,这可以用来执行清理工作。

    为了执行渲染指令,应用程序必须将这些指令记录到reshade::api::command_list中,然后提交给reshade::api::command_queue。在一些图形API中,只有一个隐含的指令列表和队列,但现代的图形API如Direct3D 12和Vulkan其实都允许创建多个这样的指令队列,以实现更高效的多线程渲染。

    ReShade将在任何此类对象被程序创建后调用reshade::addon_event::init_command_list和reshade::addon_event::init_command_queue事件(包括旧图形API的隐式事件)。类似地,reshade::addon_event::destroy_command_list和reshade::addon_event::destroy_command_queue在其销毁时被调用。

    ReShade还会将把当前的指令列表的对象传递给每一个指令事件,比如reshade::addon_event::draw, reshade::addon_event::dispatch等等,这些指令可以用来向该指令列表添加额外的命令或替换原生程序中的命令。(实际上就是Hook了)

    在屏幕上显示结果是通过reshade::api::swapchain这个交换链对象来实现的。这是一个应用程序用以渲染的缓存的集合,这些缓存最终会被呈现在屏幕上。可能会有多个交换链,例如,如果程序正在向多个窗口渲染,或者同时向一个屏幕和一个VR头显渲染。

    ReShade会在应用程序创建这样的对象后再次调用reshade::addon_event::init_swapchain事件(而reshade::addon_event::destroy_swapchain则是在销毁时)。

    此外,ReShade会在交换链创建之前调用reshade::addon_event::create_swapchain事件,所以插件可以在实际创建交换链之前去改它的描述。例如,如果要将分辨率强制为一个特定的值,可以做如下的操作:

e.其他一些注意事项

    ReShade会将一个独立的后处理效果的运行阶段与大多数交换链联系起来。这是一个通常由ReShade 覆盖层 控制的运行阶段,但它也可以通过编程方式来控制:使用ReShade API来调用reshade::api::effect_runtime对象。

    与所描述的基本API抽象对象不同,任何缓冲区、纹理、渲染管线等都是通过句柄来引用的。这些都是由应用程序创建并传递给事件(比如reshade::addon_event::init_resource, reshade::addon_event::init_pipeline, …),或者可以通过ReShade::api::device API的对象创建(通过reshade::api::device::create_resource(), reshade::api::device::create_pipeline(), …)。

    缓存和纹理是通过reshade::api::resource 句柄来引用的。深度模板、渲染目标、着色器资源或这些资源的无序访问视图通过 reshade::api::resource_view 句柄引用。而采样器状态对象通过reshade::api::sampler 句柄被引用,(部分)管道状态对象通过reshade::api::pipeline 被引用,以此类推。

资源下载: