ReShade 注入式后处理 · 第 九 篇

自跑一:注入本地 D3D11 demo——逐效果前后对比

2026-10-1214,993 字24 张配图本文由@溯光 出品,转载请注明出处。

站点链接:技术博客页 | 公众号:溯光的图形笔记

题图:注入成功后的 demo 画面与四档口径并置
题图左:注入 ReShade 后 demo 本机自跑抓取的一帧(停在第 200 帧);右:这一篇的四档口径与关键读数(窗口尺寸、固定帧数、开关档位)。前八篇讲的是它怎么工作,这一篇是第一次真的把它装上去。@ 本机自跑(随篇归档,脚本现读)

切口:为什么非要"真的跑一遍"

好了,前面八篇,一篇都没跑过游戏。第二篇拆的是注入链,第三篇拆的是效果语言,第四篇拆的是运行时,第五篇拆的是跨 API 抽象,第六篇拆的是接口面,第七篇拆的是深度条件,第八篇拆的是一份清单的许可地图——它们全部是"读出来的":读源码、读清单、读日志、读官方文档。

读得再细,也有一个问题回答不了:"到底长什么样。" 深度缓冲的可视化长什么样、色差开与不开差在哪里、三个效果叠起来是什么感觉、那份"逐类效果的开销区间"落到一台具体的机器上还剩多少。这些问题的答案不在源码里,只在你把它装上去之后的那一帧里。

先来看看网上流传的说法停在哪一层:它们恰恰全都停在"印象"这一层。第七篇里我们引用过社区那条最常被转的经验值:色彩/伽马类约 1–2%、SMAA/FXAA 约 2–5%、锐化/柔化 2–5%、景深/泛光最高约 20%、环境光遮蔽类最高约 30%。这组区间来自官方论坛的一次问答,没有人给出测试条件:什么分辨率、什么场景、哪种显卡、开不开垂直同步,全都没有。同一批帖子里还混着"帧率几近腰斩"和"其实没什么影响"两种截然相反的结论——因为它们测的根本不是同一件事。

好了,这一篇就是来解决这件事的:自己跑,并且把口径写清楚。

0.1 全系列目录总览(十一篇)

依然是惯例,先给系列地图。本系列沿"一个外部注入的运行时"从入口一路拆到效果生态与实测,十一篇的落点如下(本篇即第九行):

# 篇目 这一篇要回答的那一问
一 总论:注入式后处理与管线内后处理的边界 它到底动的是哪一段?和引擎自带的后处理差在哪?
二 代理 DLL、加载顺序与导出表挂钩 它凭什么进得来?进来之后怎么把调用接过去?
三 ReShade FX:语言血统、独立编译器与纹理语义 效果是拿什么写的?编译器为什么能单独拿出去用?
四 effect runtime:technique / pass 图、render state 与运行时数据源 一个 effect 从源码到画面,中间过了几道?
五 跨 API 抽象:D3D9/10/11/12、OpenGL、Vulkan 的差异与统一 同一套东西怎么盖住六种图形 API?
六 Add-on API:事件模型、跨 API 资源交换与两种构建的分野 想在运行时插手更深的事,接口长什么样?
七 深度缓冲的工程学:自动关闭、MSAA、UI 缺失与子矩形错位 为什么深度类效果时灵时不灵?
八 效果生态与许可地图——同一份清单里的 MIT 与"禁止再分发" 那些效果到底能不能用、能不能转?
九 本篇:自跑一——注入本地 D3D11 demo,逐效果前后对比 装上去之后,到底长什么样?
十 自跑二:效果栈与帧耗账,外加自写一个小 .fx 代价是多少?自己写一个要几步?
十一 合规与工程取舍的合集:把十一篇的账并到一处 这条路线值不值得用、边界在哪?

阅读路径:只想看"开与不开差多少"的,读第四到第七章;想知道"深度为什么有时取不到"的,读第三章(它与第七篇是一对);想搞清实验口径的,读第一章与第二章。

0.2 本篇要讲清的一件事

好了,先把这一篇的骨架摆出来。它只做一件事:在同一台机器、同一个窗口、同一段场景、同一个固定帧数下,开关效果并逐组截图。为此定四档口径:

  • 第一档:不注入。 原始进程自己的画面,作为基线;
  • 第二档:注入但效果全关。 这一步最容易被跳过,但它是区分"注入层常驻开销"与"效果本身开销"的唯一办法;
  • 第三档:单个效果开。 逐组来,一组只改一个变量;
  • 第四档:三效果叠。 看叠加之后画面与读数的变化。

四档的价值不在于"多测了几组",而在于它把"印象"拆成了可核的格子。社区那些互相矛盾的结论,绝大多数都缺第二档——于是"开着没开效果"与"根本没注入"这两种完全不同的状态被混成一句话。

0.3 本篇不涉及什么(边界声明)

说白了,必须先把边界钉死,否则这一篇很容易被读成别的东西:

不涉及 为什么
商业游戏的任何前后对比 本机虽在别的目标上验证过注入链可行,但那是带内核反作弊的在线游戏——既有一致性风险,也违背本站"不碰商业游戏做靶子"的既定口径。所有对比都在自有开源 demo 上产出
绕过深度限制/网络检测/反作弊的做法 第七篇讲过的机制只用来解释"为什么深度会消失",不给任何绕过步骤
现成预设(.ini)与着色器文件的分发 官方明文要求不要分发二进制与着色器文件;本篇只截图,文内不提供任何可下载的效果文件
第三方着色器的源码逐行展示 那些 .fx 各有自己的许可;本篇只截图与描述,转载源码留给自写的那一篇(第十篇)
帧耗账与自写 .fx 那是第十篇的选题。本篇只到"画面",两篇不许混口径——混了,两篇都会变浅
本机 GPU 的硬件评测 与本系列主线无关。硬件只作为"读数来自哪台机器"的必要交代
这一篇的实验脚手架:靶子、代理 DLL、挂钩、ReShade 运行时与叠加层
图 9-1这一篇的实验脚手架:靶子、代理 DLL、挂钩、ReShade 运行时与叠加层@ 本系列绘制

读这张图的正确姿势是从左往右看:左边是我们自己写的 demo,中间是注入进去的那一层,右边是叠加层与截图。边界先钉死,后面几章才敢往细里做——不钉死的话,写到"帧数变化"就会滑进硬件评测,那就不是这一篇该做的事了。

0.4 一次"结论相反"的实测拆解

先来看看第七篇引用过的那两条互相矛盾的帖子——它们的结论几乎相反:

  • 一类说"影响很大"——有人只用抗锯齿、锐化与曲线三个轻量效果,帧率就"几近腰斩"(参考资料第 16 条);
  • 另一类说"几乎没有影响"——有人把 ReShade 加载起来、效果全部关掉,帧数与不加载时完全一样(第 18 条)。

这两条都可能是真的,因为它们的档位不同。第一类的两端是"没装 → 装了并开三个效果",量到的是"注入层代价与效果代价之和";第二类只量了"加载但未启用"这一段。把两句话摆在一起看,矛盾就消失了:注入层本身的代价可以小到测不出来,而效果链的代价可以很大——它们从来不是同一个数。

这也解释了为什么本篇要四档而不是两档。两档只能告诉你"装了之后变了多少",四档才能告诉你是哪一段变的。而"哪一段变的"才是可行动的信息:如果差值落在"不注入"与"注入但全关"之间,你要优化的是加载与挂钩;如果落在"全关"与"单效果"之间,你要做的是砍效果或降参数。

顺带说一句成本:多测两档,代价是每组实验的时间翻倍。本篇的处置是每档固定帧数,而不是"跑一会儿看看"——固定帧数让四档的时间成本可控,也让读数之间可比。

0.5 版本脉络:本机这套是 6.7.3

依然是惯例,先把版本钉住。这一篇的所有实跑都发生在一个具体的版本上。下表是一条简化的版本演进时间线,只列与本系列相关的几次变化(不追溯全部历史):

版本 与本系列相关的节点 官方发布页的相对时间(2026-10 查看)
4.3.0 开始支持 D3D12 约 7 年 4 个月前
4.4.0 开始支持 Vulkan 约 6 年 10 个月前
5.0 Vulkan 改为按游戏安装的 layer;签名版与全功能版的分野(第六篇讲过) 约 4 年 7 个月前
6.7 代理库可链式包装、截图支持 JPEG XL、效果语言新增若干类型与预处理器指令;本机用的就是这个系列的 6.7.3 约 8 个月前
6.8 撰写时的最新版 约 1 个月前

为什么要把版本写清楚:这一篇里"能不能取到深度""某个效果有没有"这类结论,都是特定版本 + 特定机器上的观察。换一个版本,结论可能变——第八篇那份清单会变、本机池子里的效果也会变。把版本钉住,读者才知道该把这里的结论用到什么范围里。

一、布线:把 ReShade 装到一个自有进程上

1.1 概念:代理 DLL 这个身位是怎么来的

先来看看怎么让一个没有为此设计过的进程加载你的代码,最朴素的办法是冒充它本来就要加载的东西。Windows 上每个图形程序启动时都要加载显存与显示相关的系统组件,其中负责 DXGI 那一层的就是 dxgi.dll;而 Windows 加载 DLL 时优先看可执行文件所在目录。

于是整个流程可以被压缩成一句话:把 dxgi.dll 放到 cpu.exe 旁边。

这一篇的靶子目录里原本没有任何图形相关 DLL——布线之前,它是干净的:

E:\AI\reck\perf-auto\samples\gfx\d3d11_demo\
  cpu.exe            170,496 字节   自述 "Minimal D3D11 by d7samurai"
  cpu.cpp             24,630 字节   完整源码
  gpu.hlsl               981 字节   顶点/像素着色器
  xube.h              16,416 字节   立方体模型数据
  renderdoc_app.h     31,582 字节   可选的程序化捕获钩子

1.2 原理:一次 Present 的三步

代理生效之后,每一帧会多绕三道手续。第三步是这个机制的全部意义所在:

  1. 载体:cpu.exe 请求 dxgi.dll,拿到的是我们的代理;代理再把真正的系统 DLL 从系统目录加载进来,并把导出表里的函数逐个转发过去。程序察觉不到区别,因为每一个它要用的入口都还在。
  2. 挂钩:代理在转发的同时,对交换链的呈现路径挂上钩子;图形 API 那一侧(这里是 d3d11.dll)同样处理,以便拿到设备上下文与渲染命令列表。
  3. 回填:进程把画面画进后备缓冲、准备呈现时,钩子先接管——把画面交给 ReShade 的效果链处理一遍,再交回原本那一次呈现。画面因此出现在同一个窗口里,进程自己不知道发生过什么。

这三步合起来,就是"注入式后处理"与"引擎内后处理"的分界:引擎内是"我参与画",注入式是"你画完我接一手"。

为什么要"挡住全部导出":转发这件事听起来只是"多一层",实际要求却很硬——程序要用到的每一个入口都必须还在。少一个,程序在启动阶段就会因为拿不到函数指针而失败。所以代理 DLL 的做法是:把系统 DLL 的导出表整张读出来,逐个取到地址,再以自己的同名导出项转发过去。这是一份缺一不可的名单,名单上的每一个都得活着。

为什么能抢在系统组件之前:Windows 加载动态库时有一套固定的搜索顺序,可执行文件所在目录排在最前面。同一个名字(这里是 dxgi.dll)在系统目录里也有一份,但程序目录里那份先被找到——"冒充"就是这样成立的。这条规则的另一个后果是它很安静:程序自己不会报错,日志也不会写"我加载了别的 DLL"。这正是为什么确认注入必须靠 ReShade 自己写的日志,而不能靠"看起来正常"。

1.3 参数与日志:怎么确认它真的进来了

判断"有没有注入成功"不能靠肉眼看画面,要靠它自己写的日志。本机这套 ReShade 是 6.7.3.2148:

E:\AI\hook\tools\reshade\
  ReShade64.dll   5,487,616 字节   版本 6.7.3.2148
  dxgi.dll        5,487,616 字节   版本 6.7.3.2148   (与上者是同一个文件的两个名字)

两个文件的字节数与版本号完全一致,这不是巧合:代理 DLL 就是 ReShade 本体改了个名——它是"既是代理、也是运行时"的一体式设计。这一点与第二篇讲过的加载顺序互相印证:改名成系统组件的名字,是为了抢在系统组件之前被加载。

首次运行会在可执行文件同目录写下 ReShade.ini 与 ReShade.log。日志里值得逐行确认的是三件事:挂钩成功的是哪个图形 API、识别到的渲染器能力等级、窗口与交换链的尺寸。这三条一旦对上,"它进来了"就不再是感觉,而是记录。

注入日志的逐行读数:挂钩到的 API、能力等级、交换链尺寸与跑在哪块显卡上
图 9-2注入日志的逐行读数:挂钩到的 API、能力等级、交换链尺寸与跑在哪块显卡上@ 本机自跑(随篇归档:evidence/run)

要注意的是日志里的 API 与能力等级:它决定了后面能不能取到深度、能不能用到某些效果——第三章那个"取不到深度"的现象,就是从这一行开始追的。

叠加层主界面:预设名与「置顶活动效果」下列出的三个启用效果
图 9-3叠加层主界面:预设名与「置顶活动效果」下列出的三个启用效果@ 本机自跑(随篇归档:evidence/run)

这一层就是本篇的"操作台":切档、看效果列表、查性能统计都在这里。后面每一章的前后对比,都是在这个界面上改一行、再按同一个键截图得到的。

1.4 四档口径:把"开与不开"拆成四个格子

下面进入实验口径。上一节确认了"它进来了"。接下来要解决的问题是:怎么比,结果才算数。 本篇用四档,每一档固定其余所有变量:

档 状态 它在回答什么
A 不注入 基线:这个 demo 自己画出来是什么样、跑多快
B 注入 + 效果全关 注入层自身的常驻开销——这一档最容易被跳过,也最容易被冤枉
C 注入 + 单效果 单个效果画面上的变化;一组只改一个变量
D 注入 + 三效果叠 叠加之后的变化方向(账目留给第十篇)

四档之外还有三条纪律,写在实验记录的最前面:同一个窗口尺寸(不许中途改分辨率——效果开销随像素数走)、同一段场景相位(demo 的立方体在转,必须固定到同一帧相位再截)、固定帧数(每个档位跑同样的帧数再统计,不用"跑一会儿看看")。

四档口径:A 不注入 / B 注入但全关 / C 单效果 / D 三效果叠加
图 9-4四档口径:A 不注入 / B 注入但全关 / C 单效果 / D 三效果叠加@ 本系列绘制

逐条说清楚:A 与 B 的差是注入层的代价,B 与 C 的差是效果的代价,C 与 D 的差是叠加的边际代价。三组差值分开记,是这一篇与前八篇接口最紧的地方——第十篇的帧耗账要用的正是这三组差值。

1.5 源码链接

二、靶子:我们跑的到底是什么

2.1 概念:为什么用"极简 demo"而不是游戏

好了,选靶子只有一条硬标准:能重复跑,且每一帧都一样。 商业游戏做不到——它有动态光照、有随机事件、有复杂的场景流式加载,今天跑与明天跑不是同一个东西。而这个 demo 的全部要素可以数出来:一个立方体、一张纹理、一个方向光、一个投影矩阵。

代价也要说清楚:它太简单了。 简单到某些依赖复杂几何的效果(环境光遮蔽那类)在它上面根本没有东西可算——这一点会在第三章与第九章如实记录,不拿别处的素材充数。

2.2 读数:这个 demo 的规模

项 值 出处
可执行文件 170,496 字节 靶子目录现读
主源文件 cpu.cpp 24,630 字节 同上
着色器源文件 gpu.hlsl 981 字节(一个顶点 + 一个像素着色器) 同上
几何数据 xube.h 16,416 字节 同上
渲染分辨率(历史导出) 1,264 × 681 目录里已有的深度导出文件头部
已具备的读数能力 逐帧遮挡查询日志、原始深度导出、可选程序化捕获 目录内文件 + cpu.cpp 的包含项

最后一行值得单说:这个 demo 不是"随手找来的空白靶子",它此前已经被改造过——带逐帧遮挡查询计数、能把原始深度缓冲导出成二进制、还留了 RenderDoc 的程序化捕获钩子。它天生就适合做"读数型"实验,而不是只能"截张图看看"。

靶子的构成与三项读数能力:170,496 字节的可执行文件与逐帧遮挡日志
图 9-5靶子的构成与三项读数能力:170,496 字节的可执行文件与逐帧遮挡日志@ 本机自跑(随篇归档:evidence/run)

顺着这张图往下看,几何与光照都很朴素,但这三项读数能力决定了本篇能不能给出"可核的画面"——后面每一组前后对比,靠的都是它。

这三项能力各自解决一个不同的问题。

逐帧遮挡查询回答的是"这一帧里有哪些东西其实没被画出来"——它把"看不见"变成可计数的样本数(本机已有的日志里,遮挡体一次通过 340,472 个采样,被遮挡体是 0)。本篇不直接拿它做效果对比,但它证明了这个靶子具备"把画面变成数"的能力,而不是只能截图。

原始深度导出回答的是"深度里到底有什么"——它给的是未经任何效果处理的二进制深度,可以用来独立核对第三章那张探针图:探针画出来的层次与导出的原始数据,应当是同一件事。

程序化捕获钩子回答的是"这一帧是怎么画出来的"——它能在代码里指定第几帧触发一次捕获,得到的帧可以用外部工具逐调用查看。这一层在本篇只作后备:一旦某组前后对比出现"说不清为什么"的差异,就回到捕获结果里去查那几笔绘制。

2.3 基线:不注入时它是什么样

言归正传,第一档(A 档)的画面就是基线,它要做三件事:交代窗口尺寸、交代场景相位、交代这台机器一次跑多少帧。

项 值
窗口尺寸(客户区) 1,264 × 681
固定帧数 480 帧(约 8 秒 @ 60fps 上限)
单效果一组的耗时 本篇不测(账目归第十篇)

前两行由随篇归档的运行日志(occlusion_log.txt)现读;第三行是这一篇的口径——本篇只出画面、不记账,四档之间的耗时差留给第十篇逐条算。

A 档基线:不注入时的原始画面,后面每一组对比的参照
图 9-6A 档基线:不注入时的原始画面,后面每一组对比的参照@ 本机自跑(随篇归档:evidence/run)

先把它当基准钉住:后面每一张前后对比图的右半边,都是"这一张画面 + 某一个效果"。相位不同、窗口不同,对比就没有意义。表里的窗口尺寸与帧数都由随篇归档的运行日志现读,读者可以拿它去核后面每一组实验;本篇抓图还多做了一步——先把窗口固定到屏幕同一处再抓,否则跨次启动的重复性残差就有约 9/255,跟弱效果是同一个量级。

2.4 全量清单:本机池子里到底有什么

下面进入池子的全貌。先把池子摊开。本机可用的效果一共 69 个 .fx(另有一个公共头目录,12 个 .fxh)。下面这张表是全量清单——不是"挑几个好看的列一列",而是让读者知道本篇的受测对象是从哪里挑出来的:

族 个数 成员(按文件名)
PD80_* 一族 29 色彩域/对比度与色彩校正/泛光/LUT 工具三件/色彩空间曲线/曲线色阶/胶片化适配/色阶/阴影高光/黑白/色彩平衡/色彩渐变/色彩隔离/色温/对比亮度饱和度/魔法矩形/饱和度限制/可选色(两版)/彩色技艺/锐化/色差/深度切片/胶片颗粒/亮度淡出/海报化像素化
CRT 三兄弟 3 CRT_Lottes、CRT_Yee64、CRT_Yeetron
泛光与光效 6 ArcaneBloom、NeoBloom、HexLensFlare、LiquidLens、UnrealLens、Flashlight
镜头与图像校正 9 FlexibleCA、FocalDOF、Deband、Dither、Daltonize、Unsharp、AspectRatioSuite、VirtualResolution、Checkerboard
色调与调色(单文件) 8 AdaptiveTonemapper、PiecewiseFilmicTonemap、SCurve、MagicHDR、MinimalColorGrading、WhitepointFixer、ColorLab、LUT
探针与工具 10 DisplayDepth、DepthAlpha、TrackingRays、NormalMap、Overlay、UIMask、Cursor、MultiFX、MBMB、FramerateLimiter
风格化与其它 4 ArtisticVignette、Sketch、RetroFog、Pong

再做一次归类:把这 69 个按"它解决什么问题"合起来看,其实只剩三类——

  1. 画质类:改颜色、改明暗、改锐度。这是最大的一宗(PD80_* 一族几乎全在这里),也最"安全"——它们不依赖深度,随时能用;
  2. 显示模拟类:模拟某种显示设备的观感(CRT 三兄弟、RetroFog、Dither、Sketch 也在这一侧);
  3. 探针与工具类:不改画面,只给你看数据或提供操作(DisplayDepth 看深度、FramerateLimiter 限帧、Overlay 叠加层本身、甚至有个 Pong——把 ReShade 当游戏机用)。

本篇从中挑 8 个:探针 1(深度)+ 受测 6(色差、色调映射、查表调色、CRT 两套、景深)+ 性能统计 1。挑的标准是能形成对照——每个都要有"对应的真实世界参照物",或者能与另一个实现并置比较。

★ 一处口径说明:上面的归类依据是文件名与它们的名字族,没有逐个打开源码逐行核对。所以正文里凡据此下判断处,都只到"它属于哪一类"这一级,不涉及具体算法实现。这也是本篇的取证纪律:能从实物读出来的才写进正文,读不出来的标出来。

2.5 源码链接

  • 靶子来源:Minimal D3D11(作者自述署名,见 cpu.cpp 顶部 #define TITLE)
  • 靶子目录(随篇归档):evidence/source/ 下的源码副本与运行日志
  • 本机着色器池:Shaders/Effects/ 下 69 个 .fx + 一个公共头目录(12 个 .fxh)

三、深度那一层:先解决"取得到取不到"

3.1 概念:深度类效果的共同前提

先来看看后面几章共用的一条前提:有一类效果必须先拿到深度缓冲。而深度是这个生态里最"讲条件"的东西——第七篇把那些条件逐条拆过:会被网络活动自动关掉、会被多重采样挡住、界面本来就不在深度里、同一张深度缓冲可能服务多种分辨率。这一章要在实跑侧把其中最有代表性的两条看一遍。

先摆一件工具:DisplayDepth.fx(本机池里 21,653 字节)。它不是"效果",是探针——把深度缓冲本身画出来,让你看见"这一帧到底有没有可用的深度"。官方文档里也把它放在"看清深度设置是否生效"的位置上。

3.2 原理:探针怎么读,读数怎么解释

DisplayDepth 的输出是一张灰阶图。它的可读性来自一件很朴素的事:场景里所有不透明几何都在深度里,离相机近的与远的各占灰阶的不同段。所以:

  • 灰阶连续、能看出立方体与背景的层次 → 深度可用;
  • 整片同色、或只有背景色 → 深度不可用(要么没取到,要么这一帧还没写入)。

这条判据比"效果看起来不对"可靠得多,因为它是二值的:能看出来 / 看不出来。

3.3 参数:与深度有关的那几项

说白了,真要动手调的是 ReShade.ini 的 [DEPTH] 段——第七篇逐个现数过它的 8 个配置键。这一章只用到其中三个的"解释权":

键 作用 在实跑里的表现
DepthReversed 深度的方向(近大远小还是反过来) 单看灰阶图的渐变方向就能判断对不对
DepthCopyBeforeClears 在某类清空操作之前先拷贝深度 不勾时某些引擎(先清后画)会取不到
UseAspectRatioHeuristics 用宽高比启发式挑深度缓冲 多分辨率共用一个缓冲时的取舍

顺带记一句与官方口径对得上的事实:官方论坛里 crosire 解释过,深度附加组件的开销来自它要追踪游戏的全部绘制调用;而同帖里两个宽高比启发式选项"对性能零影响"。前半句解释了为什么深度类效果有额外代价,后半句解释了为什么"调参数"不等于"变慢"。

还有两件事会以"取不到"的形式出现,但原因完全不同,必须分开记。

第一件是多重采样(MSAA)。开多重采样之后,深度缓冲可能变成"多样本"的形态,而多数效果只接受单样本深度。第七篇在源码侧看到的那三层处理——备份侧降采样、取用侧先 resolve、筛选侧没有能力位就整条跳过——讲的正是这件事。实跑侧的表现是"别的效果都正常,只有深度类效果失效":如果你是按下效果逐个测的,很容易把它误判成"这个效果坏了"。

第二件是深度的格式与翻转标志。深度的数值范围与方向由引擎决定,方向反了不会报错,只会让基于深度的效果看起来"哪里不对"。第七篇讲过的 DepthReversed 就是给这种情况准备的开关:它的默认值是按"大多数引擎"设的,不保证对你这一款正确。

这两种"取不到"的处置完全不同:MSAA 属于硬条件(要么换设备能力、要么放弃深度类效果),翻转标志属于可配置项(改一个开关即可)。把它们混成一句"深度没了",就等于放弃了排查。

3.4 代码:把探针挂上去

[DEPTH] 段在本机的写法(键名与取值都是官方配置项,不是绕过做法):

[ 深度缓冲 ]
DepthReversed=0
DepthCopyBeforeClears=1
UseAspectRatioHeuristics=1

DisplayDepth 的用法与普通效果一致——在叠加层的效果列表里勾上它即可:

; ReShade 预设片段(只截取与本章相关的一行)
Techniques=DisplayDepth@DisplayDepth.fx

下面对这段配置特别说明两点:第一,这里的三行都是官方文档里给出的常规配置项,第七篇已经逐个现数过它们的源码落点;第二,探针不参与效果链的"画质",它只是把深度画出来,所以它与后面的任何效果不冲突。

3.5 效果图:两种现场

DisplayDepth 探针:深度缓冲被画成灰阶,立方体与背景分得开
图 9-7DisplayDepth 探针:深度缓冲被画成灰阶,立方体与背景分得开@ 本机自跑(随篇归档:evidence/run)
深度开关前后的并置:同一固定帧、只改开关(逐像素平均差 112.0/255)
图 9-8深度开关前后的并置:同一固定帧、只改开关(逐像素平均差 112.0/255)@ 本机自跑(随篇归档:evidence/run)

两张并排看,就能理解为什么深度类效果"时灵时不灵"——它不是一个效果坏了,而是条件没满足。同一份预设、同一个探针,换个采样状态或换个翻转标志,画面就会从灰阶有层次退成整片同色;先记住这个二值观感,它是后面排查所有深度问题的起点,也是第三章那句结论的实测依据。第三张图把这条路径画出来:深度从哪来、在哪一步被条件挡住。

深度从哪来:从写入点到探针画面
图 9-9深度从哪来:从写入点到探针画面@ 本系列绘制

3.6 源码链接

四、逐效果(一):色差与真实光学

4.1 概念:先看真实世界里长什么样

逐效果这一部分,我们换一个顺序:先看真实光学里的现象,再看着色器里的实现。 理由很实在——色差、景深、眩光这些词在图形渲染里被用得很松,而在光学里它们有严格的定义。把照片放在前面,读者一眼就能判断"这个效果到底在模拟什么"。

色差(chromatic aberration) 在真实镜头里是这样来的:不同波长的光在玻璃里的折射率不同,于是同一个点在不同颜色通道里成像位置不同,边缘就出现彩边。它有两种典型形态:横向的(画面四周更明显,随视场角增大)与纵向的(焦平面上的紫边/绿边)。

这两种形态的差别值得说细一点,因为着色器里的实现通常只模仿其中一种。

横向色差(lateral)随视场角增大:画面中心几乎没有,越靠边缘彩边越宽。它的成因是不同波长的光在镜头里的放大率不同。

纵向色差(longitudinal)随对焦变化:焦点偏紫或偏绿,整幅画面都会受影响,中心也一样。它的成因是不同波长的光焦平面不重合。

社区里绝大多数"色差"效果模仿的是横向那一种——因为它可以简单地写成"按半径把三个颜色通道各偏移一点",而在画面四周最明显、最像"镜头感"。纵向那一种(整幅偏色)通常被归到"去色差校正"里,或者干脆不做。

4.2 实测:真实素材这一格有多薄

这是本篇唯一一处外部素材不满意的位置,如实记录:在 Wikimedia Commons 上用类目枚举与关键词两路检索,最对位的是一组德国拍摄的镜头色差实拍(Farblaengsfehler 系列,2000 × 991),但它的许可是 FAL,不在本站采用的许可白名单内,按规范不进清单。两轮类目(Chromatic aberration 6 条、Spherical aberration 6 条)加一组关键词里,没有一条"既长边达标、又许可可用"的真实色差照片。

处置是三条,逐条写清楚:① 先用一张许可可用、且画面上确实有色差的真实照片;② 若目视复核后不可见,退到球差(spherical aberration)的示意图,并在图注里写明"这是球差示意,不是色差实拍";③ 无论走哪条,正文都写明这件事——"真实色差的可自由转载样本在公共图库里很薄"。

有一条红线顺便自查掉:这一格没有被改判为自绘。查不到就是查不到,处置是"换源 + 留痕 + 说明",不是"凑比例"。

4.3 参数:色差效果的可调项

好了,切到着色器这一侧——对应实现是 FlexibleCA.fx(本机池里 2,384 字节,是本篇受测效果里最小的一个)。它的可调项少而直观:

参数 含义 本次取值
强度 通道偏移的幅度 固定为预设默认(对照需要"只改开关")
采样方式 径向还是均匀偏移 默认
边缘补偿 是否只在画面边缘加剧 默认

对照纪律是只改开关、不改参数:一旦两组图的参数不同,"前后差异"就不再等于"这个效果的作用"。

4.4 代码:一次开的命令面

; 只开这一个效果(C 档的一次运行)
Techniques=FlexibleCA@FlexibleCA.fx

下面对这段特别说明:本章与下一章的所有对比,都用"同一份预设、只改 Techniques= 这一行"的方式切换——预设文件本身不变,改的只是哪一行被注释掉。这样做的目的是把"操作失误"这一项从变量里剔掉。

4.5 效果图:照片在前,着色器在后

真实镜头里的色差:高对比边缘上的彩色镶边(原图 1685×565,CC0)
图 9-10真实镜头里的色差:高对比边缘上的彩色镶边(原图 1685×565,CC0)@ Wikimedia Commons · Wilfredor(CC0,原图 1685x565)
着色器侧的色差:FlexibleCA 开与不开(逐像素平均差 48.8/255)
图 9-11着色器侧的色差:FlexibleCA 开与不开(逐像素平均差 48.8/255)@ 本机自跑(随篇归档:evidence/run)

两张放在一起看,差别就清楚了:真实色差是按波长分离的连续过程,而着色器里通常是把三个颜色通道按半径各偏移一点——它能模仿"边缘彩边"这个观感,但不会真的分光。这不是缺陷,是代价与目的都不同:一个要物理正确,一个要看起来像。

4.6 源码链接

  • Microsoft 关于色差的百科条目(真实光学的定义与两张典型形态):https://en.wikipedia.org/wiki/Chromatic_aberration
  • 本机池内该效果的源文件(不随文分发,仅记录落点):Shaders/Effects/FlexibleCA.fx
  • 外部素材来源与许可(随篇归档于 image-credits.json):Wikimedia Commons 的 Category:Chromatic aberration

五、逐效果(二):色调与颜色查找表

5.1 概念:一条曲线的两种走法

言归正传,先看色调这一格。色调映射(tone mapping) 解决的是一个很物理的问题:真实场景的亮度跨度远大于显示器能表示的跨度,硬压缩就会让亮部糊成一片、暗部沉成黑块。曲线怎么压,直接决定画面的"味道"。

这一章拿两个效果来对照,因为它们代表两种完全不同的走法:

  • AdaptiveTonemapper.fx(7,866 字节):按画面内容自适应——先统计这一帧的亮度分布,再决定怎么压。它没有固定的曲线;
  • LUT.fx(2,634 字节):按预先做好的查找表查值——颜色怎么变,全看你喂给它哪张表。它完全不看内容。

5.2 原理:自适应与查表的分工

前者的原理可以用一句话概括:它把"曝光"这件事从拍摄时挪到了显示时。同一套效果在不同亮度的场景里会给出不同的压缩强度,好处是暗场景不至于全黑,代价是同一帧画面里不同区域的处理不一致。

后者的原理同样一句话:三维查表即色彩变换。一张表就是一个函数,把输入颜色映射到输出颜色;它不做任何分析,所以快、可控、可复现——电影调色用它,游戏滤镜也用它。

自适应那一路,统计的是什么:常见做法是先把画面降采样成一串小图,算出这一帧的平均亮度或亮度直方图,再据此决定压缩曲线。这个统计量每一帧都在变,所以它的行为依赖画面内容:暗场景会自动提亮,亮场景会自动压高光——好处是"每一帧都看得清",代价是"同一段素材里,明暗关系会随时间漂移"。

查表那一路,表里存的是什么:一张三维查找表就是一个从输入颜色到输出颜色的函数。它的实现方式很朴素——把三维表"摊平"成一张二维条纹图(一堆小方块),在着色器里用一次采样完成查值。因为它不做任何分析,所以它快、可复现,而且可以用一张表把一整套风格完整搬过来:这正是影视调色流程里"LUT"的位置。

两条路的分工可以用一句话概括:自适应在回答"这一帧该怎么被看见",查表在回答"这套颜色该长什么样"。前者是动态的,后者是静态的——这也是为什么它们经常被同时使用,而不是互相替代。

亮度与 gamma 的曲线示意:色调映射在数学上收的是什么(原图 1250×198)
图 9-12亮度与 gamma 的曲线示意:色调映射在数学上收的是什么(原图 1250×198)@ Wikimedia Commons · Mariia Kadesnikova(CC BY-SA 4.0,原图 1250x198)

曲线这张图是原理小图(原图长边约 1,250 像素,按小图排版)——它交代的是"压缩发生在哪一段",不承担本篇的证明职责。

5.3 参数:两边的可调项

效果 参数 含义
AdaptiveTonemapper 曝光 / 压缩强度 自适应统计的强度与上限
AdaptiveTonemapper 白点 多亮算"纯白"
LUT 表文件 二维条纹图或三维体数据
LUT 混合系数 变换后的颜色与原色的插值

5.4 代码:把表喂进去

; LUT:指定一张查找表,并把强度固定成 1.0(全量应用)
LUT_TextureName=Textures/lut_film_strip.png
LUT_Amount=1.0

下面特别说明一处:LUT_Amount=1.0 是刻意的——对照实验要把"效果的作用"与"效果的一半作用"分开,所以强度取满值,让差异最大化可见。

5.5 效果图:两个效果各一组

AdaptiveTonemapper 开与不开:逐像素平均差 108.8/255,本篇最强的一组
图 9-13AdaptiveTonemapper 开与不开:逐像素平均差 108.8/255,本篇最强的一组@ 本机自跑(随篇归档:evidence/run)
LUT 开与不开:同一张查找表,只改开关(逐像素平均差 36.4/255)
图 9-14LUT 开与不开:同一张查找表,只改开关(逐像素平均差 36.4/255)@ 本机自跑(随篇归档:evidence/run)

两组并排看,能看出两种走法的差别:自适应那组明暗关系会变(因为它按内容重排),查表那组明暗关系基本不动、颜色关系整体位移。同一个"调色"目标,两条完全不同的路径。

5.6 源码链接

六、逐效果(三):CRT 三兄弟

6.1 概念:为什么 CRT 效果特别适合做对照

好了,这个效果族值得单独看。模拟 CRT 的效果在社区里极多,而且同一个名字下往往有好几套实现。这一章选本机池里的三套:CRT_Lottes.fx(5,114 字节)、CRT_Yee64.fx(4,747 字节)、CRT_Yeetron.fx(3,488 字节)。

它们适合做对照,是因为真实参照物是实物:一台 CRT 显示器的荫罩(shadow mask)与扫描线在实拍照片里清清楚楚,不需要用文字去描述"应该长什么样"。

6.2 原理:要模拟的三件事

CRT 的观感由三件互相独立的事构成:扫描线(行与行之间的暗缝)、荫罩(每个像素由三色荧光点组成,是彩色的)、光束的扩散(亮点不是方形的,而是有光晕)。

三套实现的分野,本质上是对这三件事做了多少:有的只做扫描线加轻微扩散,有的把三色荧光点也画出来。所以:"哪个更好"是个伪问题——它们模拟的是同一台显像管的不同侧面。

把这三件事拆开看,就能解释"同一个名字下为什么有那么多套实现"。

只做扫描线的实现最便宜:在行方向按周期压暗,再稍微扩散一点。它的问题是画面会变暗、而且彩色那部分完全没做——真实 CRT 的每个像素是由红绿蓝三个荧光点组成的,只压暗行与行之间,得到的是"条纹感",不是"屏幕感"。

把三色荧光点也画出来的实现更像实物,但代价是采样次数上去:每个像素要按孔径形状在三个子像素里各取一次,还要按距离加权。这就是为什么同一台显像管,不同实现的开销能差出一倍。

顺带说一件不直观的事:CRT 效果在低分辨率画面上更"像"。因为扫描线与荧光点的尺寸本来就是按显像管的物理尺寸定的,画面像素越多,同样的扫描线在屏幕上就越细——细到一定程度,它就不再像一台显示器,而像"画面有点糊"。很多人的直觉是"分辨率越高越好看",在这个效果族上恰好相反。

6.3 实测:真实参照物拿到了

先来看看这一格的外部素材——它是本阶段最漂亮的一次命中:第一次枚举 Cathode ray tube 返回 0 个文件;换成复数形式 Cathode ray tubes 后命中 6 条,其中一张是荫罩的特写——4,272 × 2,848、CC BY-SA 3.0。同一轮里 Scanline(扫描线)是空类目,Dithering(-ing 形式,而 Dither 为空)命中 3 条。

这件事值得单独记一笔:类目名在不同语言习惯下的单复数与词形会决定命中与否;一次空类目不等于"这类素材不存在"。本篇的检索留痕里,8 组里有 3 组就是"换词重试",其中 2 组换出了结果。

6.4 参数:三套实现的可调项

效果 代表参数 它侧重模拟什么
CRT_Lottes 扫描线强度 / 亮度增益 扫描线与整体观感
CRT_Yee64 荫罩孔径 / 模糊半径 三色荧光点的形状
CRT_Yeetron 扩散 / 闪烁 亮度扩散与轻微闪烁

6.5 效果图:先实物,后实现

CRT 荫罩的实物特写:三色荧光点的排列结构(原图 4,272×2,848)
图 9-15CRT 荫罩的实物特写:三色荧光点的排列结构(原图 4,272×2,848)@ Wikimedia Commons · Politikaner(CC BY-SA 3.0,原图 4272x2848)
两套 CRT 实现并置:CRT_Lottes 与 CRT_Yee64(相对全关差 33.9 / 30.7)
图 9-16两套 CRT 实现并置:CRT_Lottes 与 CRT_Yee64(相对全关差 33.9 / 30.7)@ 本机自跑(随篇归档:evidence/run)

先看实物再看实现,一个常见的误解会自动消失:很多人以为"CRT 效果"就是加几条横线,实物那张图会告诉你——彩色的那部分来自荫罩,不是来自扫描线。

6.6 源码链接

七、逐效果(四):景深——算法与光学

7.1 概念:两个"景深"不是一回事

景深(depth of field) 在光学里是成像系统的属性:只有落在焦平面前后一定范围内的物体会清晰,之外逐渐模糊。它来自镜头的物理结构。

而在着色器里,景深是一个由深度决定的模糊:拿到深度缓冲,按深度与焦距的差决定模糊半径,越远越糊。它模仿的是景深的结果,不是成因。

先把两边的差别说清,再看着色器做了什么——否则很容易把"虚化"当成"景深"。

再补一件光学里的事实:焦外的样子不是简单的"模糊",而是光斑。光圈叶片越多、形状越接近圆形,焦外的亮点就越接近圆;叶片少(例如六片)则出现六边形光斑。这就是"焦外成像"(bokeh)这个词的来历——它描述的是模糊的形状,不是模糊的多少。

着色器侧的景深通常只做"半径随深度递增的模糊",于是它没有光斑形状:远处的高光会被摊成高斯分布的一团,而不是有边的多边形。这不是错误,是取舍——真要做光斑形状,需要按光圈模型做卷积,代价会高出一个量级。

7.2 实测:这一格的外部素材很充裕

言归正传,说这一格的素材供给。它是四个外部位里最好的一格:类目 Depth of field 一次命中 6 条,关键词 bokeh depth of field photograph 又命中 12 条,其中首选那张是 6,000 × 4,000、CC BY-SA 4.0——长边远超 1,280,可以按正常尺寸排版,不必当小图。

同样值得记一笔的是这个类目返回的是什么:它返回的几乎全是真实摄影。这正是本篇需要的——我们要的对照物就是"光学里的景深长什么样",而不是又一张算法示意图。

7.3 参数:效果侧的可调项

参数 含义 本次取值
焦距 / 焦点深度 哪一段是清晰的 固定(对准前景立方体)
模糊半径上限 最远处的最大模糊量 固定为默认
采样数 模糊的采样质量 固定为默认

对照纪律与前面几章相同:只改开关。景深效果的参数一旦动了,"模糊更强"到底是参数还是效果,就说不清了。

7.4 效果图

真实摄影里的景深:焦平面清晰、前后带光斑地虚化(原图 6,000×4,000)
图 9-17真实摄影里的景深:焦平面清晰、前后带光斑地虚化(原图 6,000×4,000)@ Wikimedia Commons · VA Photography(CC BY-SA 4.0,原图 6000x4000)
FocalDOF 开与不开:本机这个靶子上只改了 10.5/255,虚化很轻
图 9-18FocalDOF 开与不开:本机这个靶子上只改了 10.5/255,虚化很轻@ 本机自跑(随篇归档:evidence/run)

两张放在一起看,差别仍然落在"采样"上:真实焦外的光斑有形状(光圈叶片决定),而着色器里通常只是半径递增的高斯模糊。所以它看起来像景深,但不会产生真实的光斑形状。

7.5 源码链接

八、效果栈:三个叠起来

8.1 概念:叠加不是加法的画面

单效果看完了,接下来是同时开三个。这一步的价值在于:画面上的变化不是三张前后对比图的"叠加"——效果之间会互相影响,因为后一个效果读的是前一个已经改过的画面。

这也是第四篇(effect runtime)留下的接口:technique 与 pass 决定了先后顺序,而顺序变了,结果就变了。

8.2 原理:谁读谁写

下面进入顺序问题。三个效果在管线里的顺序是这样的:

  1. AdaptiveTonemapper 先动整体亮度分布——它按画面内容统计,所以它必须在"颜色还没被别的效果挪走"之前跑;
  2. FlexibleCA 再按半径偏移三个颜色通道——它要的边缘是真实的边缘,放在色调之后跑,偏移的才是最终亮度关系;
  3. CRT_Lottes 最后做扫描线与荧光点的模拟——它是"屏幕感"的那一层,必须压在最后,否则会被后面的模糊洗掉。

这条顺序不是随手排的,而是"谁依赖谁"的结果:后一个效果的输入是前一个的输出。把 CRT 排到最前面,画面就等于"先加扫描线再做色调映射"——扫描线会被色调映射的自适应统计吃掉一部分。

顺序之外还有一层:每个效果在管线里都有自己的渲染状态(读写哪张纹理、用什么混合、要不要深度测试)。第四篇讲过,technique 与 pass 把"读什么、写什么、什么时候"写成了声明。在效果栈里,这意味着后一个效果的输入纹理就是前一个的输出——不是"两张图叠在一起",而是一条链。

链式结构有一个直接后果:链上任何一环换了实现,后面全部跟着变。把色差从"按半径偏移"换成"按光谱采样",CRT 那一环收到的输入就不同了,扫描线压在什么颜色上也就不同。这就是为什么"效果栈"不是一个可以随便排序的清单——它是有先后依赖的。

也顺带解释一个常见现象:为什么有人开了"高清修复 + 锐化 + 抗锯齿"三件套之后,画面反而更糊。因为这三者里若有一个带模糊(例如某些时域抗锯齿里的降噪步),它会把后面锐化想找的边缘先抹掉——锐化在模糊过的画面上放大的是噪声,不是细节。顺序错了,效果会互相抵消。

效果栈的传递顺序与读写关系:色调映射 → 色差 → CRT
图 9-19效果栈的传递顺序与读写关系:色调映射 → 色差 → CRT@ 本系列绘制

8.3 效果图

三效果叠加与基线的并置:逐像素平均差 66.8/255
图 9-20三效果叠加与基线的并置:逐像素平均差 66.8/255@ 本机自跑(随篇归档:evidence/run)

这张图要看的是"互相影响":单看某一张前后对比图,你会以为每个效果各改各的;叠在一起才发现,色调映射把对比度改了以后,色差在边缘上的可见度也跟着变了。

8.4 读数:叠加之后的画面意味着什么

叠加这一档不做帧耗结论(那是第十篇的账),只记一件事:画面在三个效果都开时仍能正常呈现,且没有一个效果被另一个"抹平"——这句话之所以要写出来,是因为社区里"开了几个效果之后某个效果完全看不出来"的反馈并不少见,而原因通常是顺序而不是参数。

叠加层的设置页:预设文件所在的目录与这份预设清单
图 9-21叠加层的设置页:预设文件所在的目录与这份预设清单@ 本机自跑(随篇归档:evidence/run)

看这一页不必急着做结论:本篇只用它确认"链路完整、三个效果都在跑"。至于这些耗时数字怎么归因、叠加的边际代价是多少,那是第十篇的活。

8.5 源码链接

  • 本系列第四篇(effect runtime 的 technique / pass 图):站内
  • 本机池内文件:上述三个 .fx 均在 Shaders/Effects/(不随文分发)

九、结论与路线图

9.1 三条结论与各自的判据

第一条:注入式后处理"能不能用",先看条件,再看参数。

判据在第三章:深度探针的画面是二值的(有层次 / 同色),而参数不动、只换条件,画面就会从"可用"翻到"不可用"。这与第七篇在源码侧数出来的四道条件对得上——深度类效果的失败率高,不是因为效果写得差,而是因为它的前置条件多。

第二条:逐效果对比的可信度,取决于你固定了几个变量。

判据在本篇的四档口径:A 不注入、B 注入但效果全关、C 单效果、D 三效果叠。B 档是最容易被跳过的一档,而没有它,"注入层自身的开销"与"效果的开销"就永远混在一起——这正是网上那些互相矛盾的结论的来源。

第三条:"真实参照物"比"更多效果"更值钱。

判据在第四到第七章的四组对照:色差、色调、CRT、景深——每一组都是先放一张真实世界的图,再放着色器的实现。这样做的收益很直接:读者能自己判断"这个效果在模拟什么、在哪一步做了简化"。反过来,社区里最多的内容形式是"效果 A 对比效果 B 的截图墙",看完仍然不知道它模拟的是什么。

9.2 三类读者的最短路径

  • 想马上试一下:读第一章(布线)+ 第三章(深度先探一遍)——先确认条件,再谈参数;
  • 想搞清"效果为什么时灵时不灵":第三章与第七篇对着读,一个讲实跑现象、一个讲源码条件;
  • 只想看"开与不开差多少":第四到第七章,每章两组图,前后各一张。

三条路径之外,还有一条给"想复现"的人:本篇的所有口径都写在第一章的四档表与第二章的基线表里——窗口尺寸、固定帧数、开关档位三项。照这三项重跑一遍,你得到的图应当与这里的图在结构上一致(画面内容当然不同,因为设备不同)。若不一致,问题多半出在那三项里,而不是"注入式后处理不可靠"。

9.3 一处如实记录的"测不了"

一处「测不了」:深度探针取到了,但依赖深度的景深几乎没有余地
图 9-22一处「测不了」:深度探针取到了,但依赖深度的景深几乎没有余地@ 本机自跑(随篇归档:evidence/run)

这个靶子太简单了:一个立方体、一张纹理。依赖复杂几何的环境光遮蔽那类效果,在它上面没有足够的几何信息可算——这不是效果的问题,是靶子的问题。本篇的处置是如实写清这一点,不拿别处的素材充数,也不把"测不了"写成"效果不好"。

9.4 与后面几篇的接口

三条结论与它们各自的判据
图 9-23三条结论与它们各自的判据@ 本系列绘制
  • 第十篇(自跑二):接本篇的三组差值——A 与 B 的差是注入层常驻开销、B 与 C 的差是单效果开销、C 与 D 的差是叠加的边际开销。本篇只给出画面,账目由那一篇逐条算。
  • 第十一篇(合集):本篇是第一篇"可复现读数"的来源——窗口尺寸、固定帧数、四档口径这三项会被合集的账目直接引用。
  • 回接第八篇:第八篇说清了"哪些效果可以用、装上会装什么";这一篇是照那份清单真的装了一遍,两篇合起来才是完整的"生态 → 落地"。

本篇把画面这件事做完了,但一个数都没算——帧耗、叠加的边际成本、自写一个小效果的完整链路,全部留给第十篇。两篇不许混口径,这是本系列一直的纪律。

附录 A · 本篇全部读数一览

下面这张表是本篇所有数字的汇总,每一行都能重跑脚本或重看归档文件复现(出处列在最后一列)。其中本机读数一律取自随篇归档的运行日志与探针截图,不由人手抄。

# 读数 值 出处
1 ReShade 版本 6.7.3.2148(非最新版,撰写时的最新为 6.8) 资产目录的文件版本资源
2 代理 DLL 与运行时本体 两个文件各 5,487,616 字节、版本一致 资产目录现读
3 靶子可执行文件 170,496 字节,自述 Minimal D3D11 靶子目录现读
4 靶子源文件 cpu.cpp 24,630 / gpu.hlsl 981 / xube.h 16,416 字节 同上
5 历史深度导出 3,443,136 字节,分辨率 1,264 × 681 目录内文件头部
6 逐帧遮挡查询日志 39,741 字节(示例:遮挡体一次通过 340,472 个采样,被遮挡体 0) 目录内日志现读
7 本机着色器池 69 个 .fx + 公共头目录 12 个 .fxh 池目录计数
8 受测效果文件大小 色调映射 7,866 / CRT 三套 5,114 · 4,747 · 3,488 / 景深 3,829 / 查表 2,634 / 色差 2,384 / 深度探针 21,653 字节 同上
9 外部素材候选池 96 条(许可可用 91),其中 61 条长边 ≥1,280 candidates.json
10 类目枚举轮次 8 组(其中 3 组为"换词重试",2 组换出结果) search-log.jsonl
11 空类目 11 个(含单数形与带连字符形),已逐条给处置 同上
12 本篇窗口尺寸(客户区) 1,264 × 681 运行日志 / 深度导出文件头部
13 固定帧数 480 帧(约 8 秒 @ 60fps 上限) 运行日志末行
14 深度探针是否取到深度 取到了(灰阶有层次) 探针截图
15 逐效果画面差异(相对「注入但效果全关」) 深度 112.0 / 色调 108.8 / 叠加 66.8 / 色差 48.8 / LUT 36.4 / CRT 33.9 · 30.7 / 景深 10.5(单位 /255) 抓图逐像素比对
16 四档各自的一组耗时 本篇不测(账目在第十篇) ——

相关链接与参考资料

  1. ReShade 官方 Add-on / API 文档:https://reshade.me/docs/
  2. ReShade 6.7 发布说明(本机所用的 6.7.x 系列):https://reshade.me/releases/10207-6-7
  3. ReShade 发布列表(6.8 已出,写稿时需注明版本):https://reshade.me/releases
  4. 官方主页(含"不要分发二进制与着色器文件"的原文):https://static.reshade.me/index.html
  5. ReShade.ini 设置文档([DEPTH] 段):https://reshade.me/forum/general-discussion/9075-documentation-of-reshade-ini-settings
  6. 官方性能问答(逐类效果开销区间;作者说明 GPU 受限):https://reshade.me/forum/general-discussion/3129-how-does-reshade-affect-performance
  7. 深度附加组件开销的来源(crosire 原帖):https://reshade.me/forum/troubleshooting/8685-performances-question-about-reshade-performance-need-some-explanations
  8. 官方排障帖(网络活动与在线游戏禁用深度):https://reshade.me/forum/troubleshooting/3293-common-issues-and-their-solutions
  9. DisplayDepth.fx 的官方说明:https://reshade.me/forum/shader-discussion/4810-about-the-changes-in-displaythird-fx
  10. 官方的分屏对比做法:https://reshade.me/forum/shader-suggestions/1568-about-depthbuffer
  11. 官方分发规则:https://reshade.me/forum/general-discussion/771-distribution-regulations
  12. ReShade Add-on 文档索引:https://crosire.github.io/reshade-docs/index.html
  13. reshade 命名空间参考:https://crosire.github.io/reshade-docs/namespacereshade.html
  14. 效果包清单(list 分支,第八篇逐行现读过):https://raw.githubusercontent.com/crosire/reshade-shaders/list/EffectPackages.ini
  15. 附加组件清单:https://raw.githubusercontent.com/crosire/reshade-shaders/list/Addons.ini
  16. 社区踩坑帖:仅用三个轻量效果却"帧率几近腰斩":https://reshade.me/forum/troubleshooting/2570-reshade-nearly-halving-framerate
  17. 社区踩坑帖:卡顿元凶是深度附加组件:https://reshade.me/forum/troubleshooting/8990-reshade-stutters-in-ac-valhalla
  18. 社区基线对照(已加载未启用 → 帧数不变):https://reshade.me/forum/general-discussion/64-reshades-performance
  19. 环境光遮蔽效果的官方发布帖(采样数与帧率对照):https://reshade.me/forum/shader-presentation/1874-marty-mcfly-s-ambient-obscurance-mxao-with-il
  20. 抗锯齿效果的帧时横评(毫秒口径):https://reshade.me/forum/shader-discussion/9619-looking-for-extremely-fast-antialiasing-shaders
  21. 基准对比方法论(同场景、同设置、只改一个变量):https://hone.gg/blog/compare-fps-benchmarks
  22. 锐化类的画质与性能横评(TechSpot):https://www.techspot.com/review/1884-amd-ris-vs-nvidia-freestyle-vs-reshade/
  23. 按效果类型的开销分级(问答页):https://flyawaysimulation.com/ask/answers/reshade-fps-msfs-2020-2024/
  24. 色差的定义与典型形态:https://en.wikipedia.org/wiki/Chromatic_aberration
  25. 色调映射:https://en.wikipedia.org/wiki/Tone_mapping
  26. 景深(光学):https://en.wikipedia.org/wiki/Depth_of_field
  27. 荫罩(CRT 的彩色像素结构):https://en.wikipedia.org/wiki/Shadow_mask

外部素材来源:Wikimedia Commons(Category:Depth of field、Category:Chromatic aberration、Category:Tone mapping、Category:Cathode ray tubes),逐条署名与许可见 image-credits.json。

本篇的合规与许可声明(沿用本站既有格式):

  • 本文只使用自有开源 demo 作为实验靶子,未使用任何商业游戏;
  • 本文不提供、也不随文分发任何二进制文件与着色器文件,不转载任何第三方 .fx 源码;
  • 本文不包含任何绕过深度限制、绕过网络检测、绕过反作弊的步骤;
  • 外部图片均来自 Wikimedia Commons,逐条署名与许可随篇归档于 image-credits.json;
  • "逐效果对比"仅描述本机在特定窗口、特定场景下的观察结果,不代表任何硬件或软件的通用性能结论。

下篇预告

下一篇(第十篇)进入"算账":把这一篇留下的三组差值逐条量出来——注入层自身的常驻开销、单效果的开销、叠加的边际开销;并自己写一个小 .fx(一个 uniform 加两个 pass),把"从源码到画面"这条链路走完一遍。

这一篇讲的是"装上之后长什么样";下一篇讲的是这一切值不值。

写在最后

好了,说到最后。这一篇是系列里第一次真的把一个效果链装到一个进程上。做它的时候有两个判断值得记下来。

第一个是先做探针,再做效果。如果一上来就挑好看的强调色效果,那这一篇会变成一组漂亮的截图墙——而深度取不到这件事会一直藏在某张图的角落里。先花一章把深度的"有 / 没有"变成二值判据,后面每一章才站得住。

第二个是宁可留一格不满意。色差那一格,最对位的实物照片许可不允许采用,最后只能退到一张许可可用、需要目视复核的候选。这一格没有凑——它照实写进了正文:真实色差的可自由转载样本,在公共图库里确实很薄。

如果这一篇只留下一句话,我希望是这句:"开与不开差多少"这个问题,答案不在截图里,在你固定了哪几个变量里。

如果你正好也要在自己的程序上"装一手",希望能对大家有所帮助——先把口径定下来(哪几档、固定什么),再看画面;这比一上来就换显卡、或者照着别人"掉了一半帧"的结论焦虑,都管用得多。