ReShade 注入式后处理 · 第 八 篇

效果生态与许可地图:同一份清单里的 MIT 与"禁止再分发"

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

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

题图:ReShade 的关于页(许可证清单)
题图ReShade 的关于页(本机现开现拍):它用到哪些开源库、各是什么许可证,原文列在这里——这一篇讲的就是这类许可证状态。@ 本机现开现拍

切口:同一份清单里的两种许可

第七篇把深度那件事讲完之后,评论区里最常出现的一个问题是另一个方向的:"那些 effect 到底能不能用、能不能转?" 这个问题听起来像法律咨询,实际上它有一个纯工程的内核——生态的入口文件长什么样。

好了,先把最反常识的那个事实摆出来。官方安装器在装效果的时候,读的是一份清单。而这份清单里,同时存在着两类许可:

  • 一部分仓库是宽松许可(permissive):MIT、BSD-3-Clause、CC0——你可以拿去改、拿去发,只要保留版权声明;
  • 另一部分是保留所有权利(All rights reserved):不许公开再分发,甚至连"独立托管一份副本"都被点名禁止;
  • 还有一类更微妙:根本没写许可的仓库——按默认规则,那也是保留所有权利。

这三类东西装在同一个安装器里,靠同一份清单分发。 这不是作者们意见不合,也不是谁在打擦边球。它是这份清单从设计上就不托管任何东西的直接后果——下面六章会把这句话拆成可核的读数。

先来看看这一篇和前后几篇的关系。第六篇讲接口面、第七篇讲深度条件,都是"往里钻";这一篇横切一刀,讲的是这批效果的外围规则:它们从哪来、谁能转、谁不能转、官方怎么在两者之间站着。

同一份清单里的两类许可:一边可自由再分发,一边保留所有权利
图 8-1同一份清单里的两类许可:一边可自由再分发,一边保留所有权利@ 本系列绘制

读这张图的正确姿势是从中间往两边看:先接受"两个数字都来自同一份清单"这个事实,再看两边的具体名字。边界先钉死,后面几章才敢往细里数——不钉死的话,写到许可就会滑进"哪种许可更好"的价值判断,那就不是本篇该做的事了。

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 代价是多少?自己写一个要几步?
十一 合规与工程取舍的合集:把十一篇的账并到一处 这条路线值不值得用、边界在哪?

阅读路径:只想解决"我的预设能不能打包 shader"的,读第三章与第八章第一节;想知道"某个效果能不能改、能不能转"的,第五章直接回答;想搞明白"官方生态到底怎么运转"的,第一到三章是主干。

0.2 本篇要讲清的一件事

下面进入正题,先把结论摆出来。

先把结论放这儿:"能不能转"不是许可条款的问题,是这份清单的形态决定的。 它一共给出四层答案:

  • 一层来自清单的形态:那 45 个包全部是"指针"——每一条都指向作者自己的仓库,官方不托管效果文件(第二章);
  • 一层来自两张名单:装哪些文件由白名单定,不装哪些由黑名单定,而黑名单可以覆盖白名单(第三章);
  • 一层来自许可的载体:许可写在什么地方有四种可能,而机器只认得出其中一部分(第四、五章);
  • 一层来自生态的分层:付费档的 shader,连指针都不在清单里(第六章)。

这四层的性质完全不同——第一层是工程形态,第二层是清单规则,第三层是识别问题,第四层是商业边界。把它们混在一起谈,就只能得到"开源就是可以随便用"或者"作者都很小气"这种没有信息量的结论;分开谈,每一层都能给出是/否。

本篇还会补一处上一轮的尾巴:第七篇逐个现数过 ReShade.ini 的 [DEPTH] 段那 8 个配置键,当时它们被讲成"用户能拧的旋钮"。而这一篇会在第七节说明另一半事实——官方自己在一款一款地替你拧,那份逐进程的兼容性清单里写着 191 次深度方向修正。

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

依然是惯例,先把边界摆在前面:

不涉及 为什么
许可条款的法律解释——某条许可在某个法域下意味着什么 本篇只做事实层:文件里写了什么字、清单怎么处理它。不做法律意见,也不给"这样用合不合法"的结论
"哪种许可更好"的价值判断 宽松与传染各有各的适用场景;本篇只把现状数清楚
商业授权谈判与定价策略 付费档的价位只作为事实列出(第六章),不评价贵贱
其它软件生态的许可对比 归各自的专题;本篇只把镜头对准这一份清单
任何绕过做法——绕过付费墙、绕过作者限定 红线。本系列全部实验都在自有开源 demo 上做,商业游戏一次都不碰

这里还要交代一件"本篇不做的事":它一次游戏都没跑。 效果装上去是什么样、帧耗涨了多少、画面差在哪,这些都要留到第九、十篇的"自跑";本篇只回答"这些效果从哪来、谁能转"。

参数口径也说一句:系列里所有"本机读数"都来自同一台机器——Windows 11(build 26200)、RTX 3060 Laptop(6144 MiB 显存)、.NET 运行时 4.8 以上。第八篇不新做实验,全部读数分两类:一类是对随篇归档的官方文件做离线解析(三份 INI + 若干许可原件),一类是对 45 个包的仓库许可做逐条探测。两类都能指到具体文件或具体 API 返回。

一、三份清单:安装器到底读什么

很多人以为"官方效果"就是"官网下载包里那些 .fx 文件"。先把这一层拆掉:安装器不打包效果,它读清单。

这句话里有两个含义值得先展开:一是"官方"并不是一个仓库,而是若干个作者仓库的集合;二是这些仓库的入口不在官网首页,而在一个只有三个文件的分支里。这张图把三份清单各自的规模与键名并排列出——后面每一章都要回到它们身上。

三份清单的字段与规模:45 个效果包、26 个 add-on、288 个进程段
图 8-2三份清单的字段与规模:45 个效果包、26 个 add-on、288 个进程段@ 官方仓库 list 分支的三份 INI 清单(随篇归档,脚本现读)

1.1 概念:清单是一份"指针表"

crosire/reshade-shaders 这个仓库有一个专门的 list 分支。里面只有三个文件(本机现数,落档 evidence/source/ep08_list_branch_tree.json):

文件 是什么 规模
EffectPackages.ini 效果包清单 415 行 / 25,198 字节 / 45 个包
Addons.ini 附加组件清单 210 行 / 13,164 字节(非空 179 行)/ 26 个包
Compatibility.ini 逐进程兼容性清单 1,364 行 / 20,320 字节 / 288 个段

一个分支、三个文件、一万多行——这就是所谓"官方的效果生态"的全部入口。

1.2 原理:每个包是一组键值

好了,先把一个包的形状看全。

EffectPackages.ini 的形态很朴素:[00]、[01]……每个方括号是一个包,包内是一组键=值。

; —— EffectPackages.ini 第 [23] 段,逐字 ——
[23]
PackageName=iMMERSE by Marty McFly
PackageDescription=Marty's Mods Epic ReShade Effects (successor to qUINT)
InstallPath=.\reshade-shaders\Shaders\iMMERSE
TextureInstallPath=.\reshade-shaders\Textures\iMMERSE
DownloadUrl=https://github.com/martymcmodding/iMMERSE/archive/main.zip
RepositoryUrl=https://github.com/martymcmodding/iMMERSE
EffectFiles=MartysMods_LAUNCHPAD.fx,MartysMods_MXAO.fx,MartysMods_SHARPEN.fx,MartysMods_SMAA.fx

下面对这段特别说明三件事:

  1. PackageName 是给人看的(安装器界面上那一行);
  2. InstallPath / TextureInstallPath 是给装用的(落到哪个子目录);
  3. 真正决定"装什么"的是最后两行——DownloadUrl(去哪取)与 EffectFiles(取哪些)。包描述里写的"Epic ReShade Effects"有多宏大,与装几个文件毫无关系:这一段只装 4 个。

1.3 参数:三份清单的键,各不相同

三份清单的键差在哪,先摆出来。

三个文件的键不是同一套:

清单 键 特别之处
EffectPackages.ini PackageName/PackageDescription/InstallPath/TextureInstallPath/DownloadUrl/RepositoryUrl/EffectFiles/DenyEffectFiles(另有 Enabled/Required) 有黑名单这一行
Addons.ini PackageName/PackageDescription/RepositoryUrl/EffectInstallPath/DownloadUrl32/DownloadUrl64 分 32/64 位两条下载地址
Compatibility.ini RenderApi(237)/DepthReversed(191)/Banned(56)/DepthCopyBeforeClears(54)/DepthUpsideDown(21)/UseAspectRatioHeuristics(7)/InstallTarget(6)/ForceInstallApi(3)/DepthCopyAtClearIndex(3)/DrawStatsHeuristic(2) 段名是进程名,不是序号

第三份清单的段名值得单独看一眼(本机现数):288 个段,288/288 全都是 [进程名.exe],例如

; —— Compatibility.ini 开头两段,逐字 ——
[HatinTimeGame.exe]
RenderApi=D3D9

# A Plague Tale: Innocence
[APlagueTaleInnocence_x64.exe]
RenderApi=D3D11
DepthReversed=1
DepthCopyBeforeClears=1

段名是进程名、上一行是游戏名注释(247 行注释里有 170 行是这种"游戏名"行)。 这意味着这份清单是按可执行文件匹配的:安装器看清目标进程叫什么,再决定塞哪些兼容性设置。

1.4 全量清单:45 个包逐条

言归正传,把 45 个包一次列全。

先给全量。 下面是 [00]–[44] 全部 45 个包(本机现数,落档 evidence/local/ep08_list_probe.json): 包名与仓库逐字取自清单,.fx 条数是该包 EffectFiles 的条目数,黑名单条数来自 DenyEffectFiles。

# 包名(PackageName 逐字) 仓库(RepositoryUrl 去前缀) .fx 条数 黑名单条数
0 Standard effects crosire/reshade-shaders/tree/slim 5 0
1 SweetFX by CeeJay.dk CeeJayDK/SweetFX 27 1
2 Legacy effects crosire/reshade-shaders/tree/legacy 20 0
3 OtisFX by Otis_Inf FransBouma/OtisFX 11 0
4 Depth3D by BlueSkyDefender BlueSkyDefender/Depth3D 1 0
5 FXShaders by luluco250 luluco250/FXShaders 34 1
6 reshade-shaders by Daodan Daodan317081/reshade-shaders 9 6
7 Shaders by brussell brussell1/Shaders 4 0
8 fubax-shaders by Fubaxiusz Fubaxiusz/fubax-shaders 23 0
9 qUINT by Marty McFly martymcmodding/qUINT 7 0
10 dh-reshade-shaders by AlucardDH AlucardDH/dh-reshade-shaders 12 0
11 Warp-FX by Radegast Radegast-FFXIV/Warp-FX 10 0
12 Color effects by prod80 prod80/prod80-ReShade-Repository 29 0
13 CorgiFX by originalnicodr originalnicodr/CorgiFX 8 1
14 Insane-Shaders by Lord of Lunacy LordOfLunacy/Insane-Shaders 16 0
15 CobraFX by SirCobra LordKobra/CobraFX 7 1
16 AstrayFX by BlueSkyDefender BlueSkyDefender/AstrayFX 11 2
17 CRT-Royale-ReShade by akgunter akgunter/crt-royale-reshade 1 0
18 RSRetroArch by Matsilagi Matsilagi/RSRetroArch 71 8
19 VRToolkit by retroluxfilm retroluxfilm/reshade-vrtoolkit 1 0
20 FGFX by AlexTuduran AlexTuduran/FGFX 2 0
21 CShade by papadanku papadanku/CShade 29 0
22 ReShade_HDR_shaders by Lilium EndlesslyFlowering/ReShade_HDR_shaders 10 0
23 iMMERSE by Marty McFly martymcmodding/iMMERSE 4 0
24 vort_Shaders by vortigern11 vortigern11/vort_Shaders 2 0
25 BX-Shade by BarricadeMKXX liuxd17thu/BX-Shade 4 1
26 SHADERDECK by TreyM IAmTreyM/SHADERDECK 3 0
27 METEOR by Marty McFly martymcmodding/METEOR 7 0
28 Ann-ReShade by Anastasia Bouwsma AnastasiaGals/Ann-ReShade 6 0
29 AdvancedAutoHDR by Pumbo Filoppi/PumboAutoHDR 2 0
30 ZenteonFX Shaders by Zenteon Zenteon/ZenteonFX 11 0
31 GShade-Shaders by Marot Mortalitas/GShade-Shaders 64 0
32 Ptho-FX by PthoEastCoast PthoEastCoast/Ptho-FX 1 0
33 potatoFX by PotatoFury GimleLarpes/potatoFX 4 0
34 The Anagrama Collection by nullfractal nullfrctl/reshade-shaders 3 0
35 Reshade Simple HDR Shaders by MaxG3D MaxG2D/ReshadeSimpleHDRShaders 3 0
36 reshade-shaders by Barbatos BarbatosBachiko/Reshade-Shaders 17 0
37 smolbbsoopshaders by smolbbsoop smolbbsoop/smolbbsoopshaders 2 0
38 BFBFX by yaboi BFB yplebedev/BFBFX 2 0
39 Rendepth by cybereality outmode/rendepth-reshade 1 0
40 Retro Shaders by P0NYSLAYSTATION P0NYSLAYSTATION/Scaling-Shaders 2 0
41 LumeniteFX umar-afzaal/LumeniteFX 5 0
42 Shades by JakobPCoder JakobPCoder/Reshade-Shades 1 0
43 verfx Shaders by vertver vertver/verfx 3 0
44 UniqFX by dwojtasik dwojtasik/UniqFX 4 0

这张表里有三件事要看:

  1. 包按作者划分,不按功能划分。 PackageName 一律是"某某的什么"(SweetFX by CeeJay.dk、OtisFX by Otis_Inf、Color effects by prod80),而不是"抗锯齿包""色彩包"。这份清单的组织单位是"作者",不是"用途"——因为它要处理的是"谁的意愿",不是"谁的功能"。
  2. 条目的量级差得很远。 最多的 RSRetroArch 有 71 条,最少的 6 个包只有 1 条。这与包的性质有关:复古滤镜那类一个文件就是一套(crt-royale.fx 一个文件就是完整的 CRT 着色器),而色彩类效果往往一个文件管一个参数族(PD80_04_* 一族十几个文件)。
  3. 黑名单只出现在 8 个包里。 另外 37 个包一个排除项都没有。这说明"提排除请求"是少数作者的个别行为,不是普遍做法——第三章会回到这一点。

1.5 二次归类:45 个包归成四类

全量清单是"面",归类是"骨"。按包的性质(不是按功能)可以把这 45 个包归成四类:

类别 判据 包数 例子
官方自带 仓库指向 crosire/reshade-shaders 自己的分支 2 Standard effects(slim 分支)、Legacy effects(legacy 分支)
个人作者的合集 一个作者一个仓库,包名带作者名 38 SweetFX、OtisFX、qUINT、iMMERSE、METEOR、prod80、FXShaders…
移植与再整理 把别处的效果搬过来或整理成集 3 RSRetroArch(RetroArch 效果整理)、CRT-Royale-ReShade(从 Libretro 移植)、GShade-Shaders(另一发行版的效果集)
特定场景工具 与 HDR、VR 等场景绑定 2 ReShade_HDR_shaders、VRToolkit

下面对这个归类特别说明一句:这不是官方分类,是为回答"这份清单由什么样的贡献者组成"而做的归类。 归完之后可以看出:这是一份"个人作者拼起来的清单"——38/45 是个人仓库,官方自带的只有 2 个。 这就提前解释了为什么许可会这么杂:清单没有一个统一的授权口径可以依赖,只能逐个仓库去问。

1.6 效果图与核对

这一节的三份清单已经由脚本逐字节归档(evidence/source/ 下三个同名文件), 任何一个数字都可以重跑 evidence/build/ep08_fetch_lists.py 复现。

源码链接:https://github.com/crosire/reshade-shaders/tree/list

这一节要说清的是"入口在哪":不是官网的一个压缩包,而是一个分支上的三份 INI。先把入口认准,后面才谈得上"谁允许装什么"。

二、指针清单:45 个包,没有一条例外

下面进入第一个硬结论。先把最容易被误读的那件事说清楚:清单不托管效果。

2.1 概念:"托管"与"指路"是两件不同的事

如果一个项目想"提供效果",它至少有两条路:

  • 托管:把效果文件收进自己的发布物(安装包里、或者自己的 release 里),用户从你这里拿;
  • 指路:不碰文件,只给一个地址,让用户的安装器去作者那边取。

这两条路的合规代价完全不同:托管意味着每一步都要取得再分发许可,指路只需尊重作者提出的限制。代价差在哪里值得说细一点:托管路线要对"每一个文件的每一次传播"负责——作者换一次许可、加一条限制,你都得跟着改;指路路线只对"我有没有如实告诉你地址"负责,作者改许可与你无关。这就是为什么一个项目想做大,几乎一定会往"指路"这一侧走。

指针证明:45 条包记录里 45 条指向作者自己的仓库
图 8-3指针证明:45 条包记录里 45 条指向作者自己的仓库@ 官方 EffectPackages.ini(随篇归档,脚本现读)· 计数由脚本现数

2.2 读数:45/45,一条例外都没有

好了,看读数。

evidence/build/ep08_derive.py 的现数:

读数 值
带 RepositoryUrl 的包 45 / 45
DownloadUrl 与 RepositoryUrl 同一个仓库宿主的包 45 / 45
下载地址指向 crosire 自己仓库的包 2 个(Standard effects、Legacy effects,都在 crosire/reshade-shaders 的 slim/legacy 分支)
其余指向第三方作者仓库的包 43 个
下载地址不是 github 的包 0 个

45 条下载地址,没有一条例外地指向"它自己那个仓库"。 换句话说:reshade-shaders 这份清单没有为任何一个第三方作者托管过哪怕一个字节——它只提供坐标。

2.3 为什么这件事重要:作者本人的原话

先来看看作者自己怎么说。

这句话不是我推的。ReShade 作者在官方论坛那帖《Distribution Regulations》里写得很直白(本机复核,逐字):

The EULA only counts for ReShade itself, which is the ReShade32.dll and ReShade64.dll, nothing more. Those I am the author of and I grant everybody to distribute them as they wish, as long as credits are given.

However, the ReShade Framework needs separate handling because I'm not the author of any of the shader files it comes with. ... At least two of them asked to not reupload their work anywhere else.

As said before I'm personally ok with the distribution of the ReShade binaries, but since the shaders are not mine, I have no right to allow that for them too, that's up to their authors.

"本体是我一个人的,效果不是我一个人的"——这半句话就是"指针清单"这个设计的全部理由。 官网下载区还把这层意思写成了给用户的操作口径(本机复核,逐字):

Use preset files (*.ini) that can be created from ReShade's in-game user interface to share your configurations. Do NOT share the binaries or shader files. Link users to this website instead.

托管与指路两条路:谁承担再分发责任,谁只对地址真实性负责
图 8-4托管与指路两条路:谁承担再分发责任,谁只对地址真实性负责@ 本系列绘制

2.5 一个包从"点安装"到"文件落盘"走了哪几步

下面进入安装链路。把上面那些键串起来,一个包的完整路径是这样的(仍然拿 [23] iMMERSE 举例):

  1. 取址:安装器读 DownloadUrl,得到 https://github.com/martymcmodding/iMMERSE/archive/main.zip—— 注意这是 GitHub 的 archive 端点,也就是"作者那个仓库的当前快照",不是官方自己的镜像;
  2. 下载与解包:把压缩包取回本地并解开;
  3. 落盘定向:按 InstallPath 把 shader 放到 .\reshade-shaders\Shaders\iMMERSE, 按 TextureInstallPath 把纹理放到 .\reshade-shaders\Textures\iMMERSE—— 两个路径分开写,因为 shader 与纹理在 ReShade 里本来就是两个搜索路径;
  4. 白名单过滤:只把 EffectFiles 里点名的 4 个文件装进去,其余文件一律不装—— 注意 iMMERSE 仓库里实际有 20 多个 .fx 文件,而清单只取了 4 个;
  5. 黑名单剔除:若该包还写了 DenyEffectFiles,就在上一步的结果里再减去这些文件 (iMMERSE 这一个包没有黑名单,但另外 8 个包有);
  6. 登记:把落盘结果告诉运行期,供效果列表加载。

第 4 步是整条链上最容易被忽略、也最关键的一步。 因为"从作者仓库下载"这个动作本身 可以覆盖整包,但清单只装它点名的那些文件——这就是白名单存在的意义: 它把"下载范围"与"安装范围"分开了。

2.6 源码链接

把这一节收成一句:这份清单是一条"路标",不是一座"仓库"。 认下这件事,第三章的两张名单才有意义。

三、白名单与黑名单:装哪些、不装哪些由谁定

第三章讲规则。这一章的两个数字是整篇最"工程"的地方:一个白名单,一个黑名单。

3.1 白名单:499 个文件,逐个点名

好了,看第一张名单。

白名单的 499 条:逐包点名要装哪些文件
图 8-5白名单的 499 条:逐包点名要装哪些文件@ 官方 EffectPackages.ini(随篇归档,脚本现读)· 计数由脚本现数

499 条、去重后还是 499 条。这个"去重前后相等"很说明问题:清单里没有重复条目, 每个文件都只在它自己的包里点了一次名。

条目分布是极度不均的:RSRetroArch 一个包就有 71 条,GShade-Shaders 64 条,而有 6 个包只列了 1 条。

; —— 条目最多的包,头几个文件(EffectFiles 逐字,截断展示)——
EffectFiles=3DFX.fx,ArtifactColors.fx,BasicCRT.fx,CRT-Frutbunn.fx,CRT-NewPixie.fx,...

; —— 只列 1 条的包之一 ——
EffectFiles=SuperDepth3D.fx
EffectFiles=crt-royale.fx
EffectFiles=VRToolkit.fx

下面对这种形态特别说明一句:白名单是逐文件的,不是"整包合并"。 所以同一个仓库里的公开子集与付费子集,在清单里可以天然分开——第六章会用到这一点。

3.2 黑名单:8 个包、20 个文件

再看第二张名单。如果说白名单回答"装哪些",黑名单回答的是另一个问题:作者明确要求"这个文件别自动下"的,有哪些。它是整份清单里唯一一处直接反映作者个人意愿的地方——白名单体现的是打包习惯,黑名单体现的才是意见。这张图把 20 个文件逐条列出(按包分组)。

黑名单的 8 个包 20 个文件:作者点名不要再分发的那些
图 8-6黑名单的 8 个包 20 个文件:作者点名不要再分发的那些@ 官方 EffectPackages.ini(随篇归档,脚本现读)· 计数由脚本现数

21 处、去重 20 个文件、落在 8 个包里。逐条如下:

包 被排除的文件
SweetFX by CeeJay.dk Template.fx
FXShaders by luluco250 GrainSpread.fx
reshade-shaders by Daodan HotsamplingHelper.fx、AdaptiveTint.fx、ColorIsolation2.fx、Composition.fx、Stats.fx、Template.fx
CorgiFX by originalnicodr StageDepthPlus_WithDepthBufferMod.fx
CobraFX by SirCobra LongExposure.fx
AstrayFX by BlueSkyDefender Limbo_Mod.fx、SnowScape.fx
RSRetroArch by Matsilagi ArtifactColors.fx、lcd-grid.fx、MAMEPostProc.fx、NTSCCustom.fx、NTSC_XOT.fx、R57_PAL_NEW.fx、sgenpt-mix.fx、Technicolor.fx
BX-Shade by BarricadeMKXX BX_XIV_ChromakeyPlus.fx

3.3 一处反直觉的机制:黑名单覆盖白名单

说白了,这一处要把两张名单并排才看得出来。

这是本篇查到的最"工程"的一处细节。 上表里有三个包,被排除的文件同时出现在这个包的白名单里:

包 既在白名单又在黑名单的文件 个数
FXShaders by luluco250 GrainSpread.fx 1
reshade-shaders by Daodan HotsamplingHelper.fx 1
RSRetroArch by Matsilagi ArtifactColors.fx、lcd-grid.fx、MAMEPostProc.fx、NTSCCustom.fx、NTSC_XOT.fx、R57_PAL_NEW.fx、sgenpt-mix.fx 7

文件先被列进"要装",再被点名为"别装"。 这不是笔误——三个包各自这么做, 说明它是清单的既定语义:DenyEffectFiles 的优先级在 EffectFiles 之上。 另有 RSRetroArch 的 Technicolor.fx 只出现在黑名单、白名单里没有它: "列进白名单再排除"与"干脆不列"两种写法都存在。

安装器用两张名单的一进一出:先按白名单取,再按黑名单剔
图 8-7安装器用两张名单的一进一出:先按白名单取,再按黑名单剔@ 本系列绘制

3.5 三个边界样本:71 条、5 条、1 条

言归正传,看三个极值。

白名单的极端值比平均值更能说明问题,取三个样本:

样本 包 条目数 说明
最大 RSRetroArch by Matsilagi 71 一整套复古显示效果(CRT、NTSC、扫描线、色度…),一个文件一套,所以条目最多
中位 —— 5 多数包在 1–10 条之间:一个作者把自己常用的几个效果列出来
最小 Depth3D、CRT-Royale-ReShade、VRToolkit 等 6 个包 1 一个包就是一个效果:SuperDepth3D.fx/crt-royale.fx/VRToolkit.fx

这三个样本合起来说明一件事:白名单的形态完全由作者自己的打包习惯决定。 有的作者把 71 个文件摊平在一个仓库里,有的作者一个仓库就一个效果—— 清单不为这件事做统一,它照抄作者的现状。

3.6 效果图:谱系图放这儿,是为了对照"为什么会有黑名单"

许可谱系:从宽松到传染再到专有(原图 1100×430)
图 8-8许可谱系:从宽松到传染再到专有(原图 1100×430)@ Wikimedia Commons · David A. Wheeler (initial), redrawn by Idrisz19(CC BY 3.0)

这张图是外部素材里最对位的一张:它把许可画成一条谱系,而不是一张"好/坏"表。 先看它与黑名单的关系:黑名单里那些文件名(Template.fx、SnowScape.fx、Technicolor.fx) 之所以能被"点名",前提是它们各自处在谱系的不同位置上——作者的意愿不一样, 清单能做的只有一件事:尊重,并且记下来。

3.7 源码链接

四、许可地图:同一份清单里的七种状态

第四章开始数许可。这一章的方法本身值得先说清楚,因为它决定了结论的可信度。

4.1 原理:一条许可是怎么被"查到"的

查一个开源仓库的许可,通常有三条路,可靠性依次递增:

  1. 看代码托管平台的字段——快,但它是机器判读,有假阴性;
  2. 看仓库里有没有许可文件——比字段准,但"没有文件"和"没说"是两件事;
  3. 读许可文件与 README 的正文——最准,也是最费事的那一步。

本篇三条都走了,而且第四条路也走了:对探测失败的仓库,再去读它的 README 里有没有许可段落。

44 个仓库的许可结论:七种状态并存,最大一格是完全未声明
图 8-944 个仓库的许可结论:七种状态并存,最大一格是完全未声明@ 代码托管平台的许可字段 + jsdelivr 补齐(随篇归档,脚本现读)

4.2 读数:七种状态并存

先来看看这七种状态各自有多少个仓库。

evidence/build/ep08_license_map.py 的输出(44 个仓库):

许可状态 仓库数 代表
MIT(宽松) 15 SweetFX by CeeJay.dk、FXShaders、prod80、CobraFX、BFBFX、UniqFX…
BSD-3-Clause 3 Daodan 的 reshade-shaders、CShade、reshade-vrtoolkit
CC0-1.0 2 CorgiFX、Insane-Shaders
GPL-2.0(传染性) 2 dh-reshade-shaders、crt-royale-reshade
GPL-3.0(传染性) 1 ReShade_HDR_shaders
有许可文件、但机器认不出(须人读) 6 iMMERSE、METEOR、OtisFX、Warp-FX、ZenteonFX、ReshadeSimpleHDRShaders
没有许可文件、但 README 里有声明 3 qUINT、Anagrama Collection、fubax-shaders
没有许可文件、README 也没有声明 10 crosire 的 reshade-shaders、Depth3D、AstrayFX、RSRetroArch、BX-Shade、SHADERDECK、Ann-ReShade、GShade-Shaders…
自定义专有许可(All rights reserved) 1 LumeniteFX(AGNYA License)
待人工归类 1 Shades by JakobPCoder(21,125 字节的长文,关键词法未归类)

七种状态,一份清单。 这不是"统计口径凑出来的七类"——每一类都有指定的判定依据: 字段能认出的、文件存在但认不出的、README 里才说的、什么都没说的。下面把这四层的证据来源逐个列清楚。

# —— evidence/build/ep08_license_map.py 的判定骨架,逐字 ——
if spdx == 'NOASSERTION':
    cls = 'proprietary:有许可文件但机器未识别(须人读)'
elif spdx:
    cls = ('copyleft:' + spdx) if spdx.startswith('GPL') else ('permissive:' + spdx)
else:
    cls = 'unresolved:API 限流'          # ← 第 39–45 条撞上 GitHub 的 403 限流
# 对 has_license_file=False 的仓库,再查 README 有没有 License 段:
#   有 → 'proprietary:无 LICENSE 文件,但 README 里有声明'
#   无 → 'proprietary:无许可文件'(README 也无声明)

下面对这段特别说明一处:unresolved:API 限流 这一格是"没问到",不是"没有"。 本轮 45 条探测里后 7 条撞上 403 —— 处理办法不是把它们记成"无许可",而是换通道重探: 用 jsdelivr 逐个仓库探 4 个常见许可文件名 × 2 个分支,结果7 个全部探到了 LICENSE (5 个 MIT、1 个自定义专有、1 个长文待归类)。"没问到"和"问到没有"必须分开记, 否则整张地图就是假的。

4.3 外部对照:许可的兼容方向

三档许可之间的兼容方向与需要单独授权的灰色区(原图 675×599)
图 8-10三档许可之间的兼容方向与需要单独授权的灰色区(原图 675×599)@ Wikimedia Commons · Morin A, Urban J, Sliz P(CC BY 3.0)

这张图画的是兼容方向:哪一档能"流向"哪一档、哪一格需要单独取得授权。 它与本篇的关系是尺度对照——清单一侧只做"记录",而这张图讲的是"流向"。 换个说法:这张图回答"两种许可能不能合到一起",而下面那张全量表回答"这一格该归到哪一类"。两者不是一回事,也不该互相替代——把尺度图当地图用,很容易得出"这份清单里全是兼容许可"这种错误结论。

4.5 全量许可清单:44 个仓库逐条

言归正传,44 个仓库一次列全。

把 44 个仓库逐个列全(本机现数,落档 evidence/local/ep08_license_map.json)。 "判定依据"那一列是关键——它说明结论是从哪一层拿到的(平台字段/许可文件/README/什么都没说):

仓库 许可结论 判定依据 服务几个包
AlexTuduran/FGFX MIT 平台字段可识别(MIT) FGFX by AlexTuduran
AlucardDH/dh-reshade-shaders GPL-2.0 平台字段可识别(GPL-2.0) dh-reshade-shaders by AlucardDH
AnastasiaGals/Ann-ReShade 未声明(无文件) 无许可文件、README 也无声明 Ann-ReShade by Anastasia Bouwsma
BarbatosBachiko/Reshade-Shaders 未声明(无文件) 无许可文件、README 也无声明 reshade-shaders by Barbatos
BlueSkyDefender/AstrayFX 未声明(无文件) 无许可文件、README 也无声明 AstrayFX by BlueSkyDefender
BlueSkyDefender/Depth3D 未声明(无文件) 无许可文件、README 也无声明 Depth3D by BlueSkyDefender
CeeJayDK/SweetFX MIT 平台字段可识别(MIT) SweetFX by CeeJay.dk
Daodan317081/reshade-shaders BSD-3-Clause 平台字段可识别(BSD-3-Clause) reshade-shaders by Daodan
EndlesslyFlowering/ReShade_HDR_shaders GPL-3.0 平台字段可识别(GPL-3.0) ReShade_HDR_shaders by Lilium
Filoppi/PumboAutoHDR MIT 平台字段可识别(MIT) AdvancedAutoHDR by Pumbo
FransBouma/OtisFX 专有/未识别 有许可文件、平台字段未识别 OtisFX by Otis_Inf
Fubaxiusz/fubax-shaders 未声明(无文件) 无许可文件,README 有关键词 fubax-shaders by Fubaxiusz
GimleLarpes/potatoFX MIT 平台字段可识别(MIT) potatoFX by PotatoFury
IAmTreyM/SHADERDECK 未声明(无文件) 无许可文件、README 也无声明 SHADERDECK by TreyM
JakobPCoder/Reshade-Shades 待归类 有许可文件(长文,待人工归类) Shades by JakobPCoder
LordKobra/CobraFX MIT 平台字段可识别(MIT) CobraFX by SirCobra
LordOfLunacy/Insane-Shaders CC0-1.0 平台字段可识别(CC0-1.0) Insane-Shaders by Lord of Lunacy
Matsilagi/RSRetroArch 未声明(无文件) 无许可文件、README 也无声明 RSRetroArch by Matsilagi
MaxG2D/ReshadeSimpleHDRShaders 专有/未识别 有许可文件、平台字段未识别 Reshade Simple HDR Shaders by MaxG3D
Mortalitas/GShade-Shaders 未声明(无文件) 无许可文件、README 也无声明 GShade-Shaders by Marot
P0NYSLAYSTATION/Scaling-Shaders MIT 平台字段可识别(None) Retro Shaders by P0NYSLAYSTATION
PthoEastCoast/Ptho-FX MIT 平台字段可识别(MIT) Ptho-FX by PthoEastCoast
Radegast-FFXIV/Warp-FX 专有/未识别 有许可文件、平台字段未识别 Warp-FX by Radegast
Zenteon/ZenteonFX 专有/未识别 有许可文件、平台字段未识别 ZenteonFX Shaders by Zenteon
akgunter/crt-royale-reshade GPL-2.0 平台字段可识别(GPL-2.0) CRT-Royale-ReShade by akgunter
brussell1/Shaders 未声明(无文件) 无许可文件、README 也无声明 Shaders by brussell
crosire/reshade-shaders 未声明(无文件) 无许可文件、README 也无声明 Standard effects、Legacy effects
dwojtasik/UniqFX MIT 平台字段可识别(None) UniqFX by dwojtasik
liuxd17thu/BX-Shade 未声明(无文件) 无许可文件、README 也无声明 BX-Shade by BarricadeMKXX
luluco250/FXShaders MIT 平台字段可识别(MIT) FXShaders by luluco250
martymcmodding/METEOR 专有/未识别 有许可文件、平台字段未识别 METEOR by Marty McFly
martymcmodding/iMMERSE 专有/未识别 有许可文件、平台字段未识别 iMMERSE by Marty McFly
martymcmodding/qUINT 未声明(无文件) 无许可文件,README 有声明 qUINT by Marty McFly
nullfrctl/reshade-shaders 未声明(无文件) 无许可文件,README 有关键词 The Anagrama Collection by nullfractal
originalnicodr/CorgiFX CC0-1.0 平台字段可识别(CC0-1.0) CorgiFX by originalnicodr
outmode/rendepth-reshade MIT 平台字段可识别(None) Rendepth by cybereality
papadanku/CShade BSD-3-Clause 平台字段可识别(BSD-3-Clause) CShade by papadanku
prod80/prod80-ReShade-Repository MIT 平台字段可识别(MIT) Color effects by prod80
retroluxfilm/reshade-vrtoolkit BSD-3-Clause 平台字段可识别(BSD-3-Clause) VRToolkit by retroluxfilm
smolbbsoop/smolbbsoopshaders MIT 平台字段可识别(MIT) smolbbsoopshaders by smolbbsoop
umar-afzaal/LumeniteFX 自定义专有 有许可文件(自定义条款) LumeniteFX
vertver/verfx MIT 平台字段可识别(None) verfx Shaders by vertver
vortigern11/vort_Shaders MIT 平台字段可识别(MIT) vort_Shaders by vortigern11
yplebedev/BFBFX MIT 平台字段可识别(None) BFBFX by yaboi BFB

这张表要横着读,不要只读第二列。同一列"许可结论"里,判定依据的差别很大:

  • 写着 MIT 的那些,多数是平台字段直接可识别——证据最硬;
  • 写着 专有/未识别 的 6 个(含 iMMERSE、METEOR)是有许可文件、机器没认出来, 结论来自人读文件;
  • 写着 未声明(无文件) 的 10 个是既没有常见许可文件、README 里也没有声明—— 这是整张表里最大的一格,第五章会专门讲它为什么危险。

4.7 七种状态与"能不能转"的对应

把这一章的结论翻成一句能被直接使用的话——每种状态对应什么样的处置:

许可状态 仓库数 能不能再分发 该做什么
CC0 2 可以 无需署名(但还是写上更体面)
MIT 15 可以 保留版权与许可声明
BSD-3-Clause 3 可以但有限制 除了保留声明,还不能用作者名义背书(第三条款)
GPL-2.0/GPL-3.0 3 可以但要同许可 衍生作品必须继续以 GPL 发布
自定义专有 1 不可以(须逐个取得许可) 去问作者
有文件但机器认不出 6 取决于文件正文 人读一遍——其中就有实为 MIT 的(5.1)
只在 README 声明 3 取决于声明 读 README,别只看有没有 LICENSE
完全未声明 10 默认不可以 按保留所有权利处理;想用就去联系作者

这张表的第三列不是法律意见,它只是"文件里写了什么"的翻译。把它当操作清单用: 先看仓库落在哪一行,再决定下一步。

要注意的是最后一行:10 个仓库占了 44 个的将近四分之一。 在这份清单里,"没有声明"比"任何一类明确许可"都更常见。 这一格之所以危险,恰恰因为它最不起眼——它看起来只是"信息缺失", 实际后果是默认的保留所有权利。

4.8 把七种状态排成一级阶梯

好了,把七种状态排成一级看。

七级阶梯:从 CC0 到完全未声明,每一级的再分发默认答案
图 8-11七级阶梯:从 CC0 到完全未声明,每一级的再分发默认答案@ 本系列绘制

这一节最后要说清一件事:阶梯上的前五级是"作者明确表了态",后两级(未声明)是"作者没有表态"。 这两者在法律后果上等价,但在工程处理上不等价—— 前者可以按条款来做自动化检查,后者只能靠人工逐个联系作者。第五章讲的就是这个分界线。

五、两种 null 与四种载体:机器判不了的那一半

第五章是本篇最"工具论"的一章:机器给的两个 null,含义完全不同。

5.1 两个反例,先看原文

两个反例逐字对照:有文件却认不出,与没文件但 README 有声明
图 8-12两个反例逐字对照:有文件却认不出,与没文件但 README 有声明@ 官方仓库 OtisFX__LICENSE 与 qUINT__README.md(随篇归档)

反例一:OtisFX —— 有许可文件,机器认不出。

这个仓库在平台字段里的判定是"未识别"(NOASSERTION)。但把它落档的许可文件打开(evidence/source/OtisFX__LICENSE,1,191 字节),开头是这两行:

The MIT License (MIT)

All shaders except PandaFX: Copyright (c) 2018 Frans Bouma
PandaFX: Copyright (c) 2018 Jukka Korhonen aka Loadus ~ twitter.com/thatbonsaipanda

正文就是标准 MIT。 机器为什么认不出?因为标准 MIT 的判读通常期望版权行紧跟在标题之后, 而这里插了两行按文件区分归属的说明。人一眼就知道结论,机器不知道。

反例二:qUINT —— 没有许可文件,但 README 里说了。

这个仓库根目录没有 LICENSE/LICENSE.md/LICENSE.txt/COPYING 中的任何一个 (本机用 4 个常见文件名 × 2 个分支逐个探过)。但它的 README 末尾有这么一段(落档逐字):

License
------------------------
### Copyright (c) Pascal Gilcher / Marty McFly. All rights reserved.

"没有许可文件" ≠ "什么都没说"。 只按文件名判定,这个仓库会被错记成"完全未声明"。

5.2 四种载体与识别顺序

说白了,这一节讲的是"该往下读几层"。四种载体的识别成本并不一样:许可文件机器多数能读出来,README 段落机器基本不读,源文件注释要逐文件扫,而"什么都没写"在字段上与"认不出"长得一模一样。下面这张表把四种载体各自的仓库数一并列出。

许可的四种载体:机器只读得到一个,其余三个都要人看
图 8-13许可的四种载体:机器只读得到一个,其余三个都要人看@ 本系列绘制
载体 仓库数 机器能自动认出吗
独立的许可文件 29(含 6 个"有文件但认不出") 大部分能,按文件区分归属等写法会漏
README 里的许可段落 3 不能(平台不读 README 的许可段)
源文件里的注释声明 未逐文件统计(本轮在搜索中见到实例) 不能(要逐文件扫)
什么都不写 10 "认不出"与"没写"在字段上长得一样

这就是本篇最实用的一条结论:查一个效果的许可,只能得到"下限"。 字段说"有许可",那就是有;字段说"没有",还得去看 README、看源文件注释。

5.4 把三级判定跑一遍:以 OtisFX 为例

前面说的是方法,这里把它跑一遍,看三级各给出什么:

步骤 看到的东西 结论
第一级:平台字段 NOASSERTION("有文件但未识别") 判不了——这一级只能说"仓库里有许可相关的东西"
第二级:有没有许可文件 有,LICENSE,1,191 字节 文件存在,但字段已经告诉你机器读不懂
第三级:读文件正文 标题是 The MIT License (MIT),随后两行按文件区分归属,正文是标准 MIT 结论:MIT(宽松许可)
补一级:README 复查 该仓库 README 无额外限制条款 不改变结论

这个流程走完只花了几分钟,但三级缺一不可。 只走第一级,这个仓库会被归进"未识别"(本篇表里的第 6 格); 只走前两级,就会把它与"完全未声明"混为一谈。而实际结论是——它是一个可以自由再分发的 MIT 仓库。

换句话说:查询一个效果的许可,成本不在读条款,而在"知道要往下读几层"。

5.5 三级判定跑不动的时候怎么办

先来看看"跑不动"这种情况。

上一条流程有个前提:你知道去哪读。但现实里有一种情况更麻烦—— 平台限流。本轮 45 条探测里后 7 条就撞上了 HTTP 403。

这一处的处置值得记下来,因为它是"机械结论不可信"的另一面:

现象 错误处置 正确处置
平台返回 403 记为"没有许可" 记为"没问到",换通道重探
换通道后探到 LICENSE —— 按文件名与首行判类别(本轮 7 个里有 5 个是 MIT)
换通道后探不到任何许可文件 记为"无许可" 再查 README(见 5.1 的 qUINT 反例)
全都探不到 记为"未声明" 并注明探测过的文件名与分支,留下可复核的痕迹

这张表就是本篇的"方法学"部分。 它比结论重要——因为换个人、换一天,同样的清单可能查出不同的地图; 只有把"怎么查的"写清楚,那张地图才是可复核的。

5.6 传染性那一侧:GPL 与 copyleft

上面那张地图里,传染性许可只有 3 个仓库(GPL-2.0 两个、GPL-3.0 一个),占比不高, 但它决定了能不能与别的代码混在一起,所以必须单独看一眼。

哪些许可可以进入 GPL 工程、哪些不能(原图 1665×850)
图 8-14哪些许可可以进入 GPL 工程、哪些不能(原图 1665×850)@ Wikimedia Commons · User:HarJIT (talk)(CC BY 4.0)
copyleft 的传播链:衍生作品继续受同一许可约束(原图 722×261)
图 8-15copyleft 的传播链:衍生作品继续受同一许可约束(原图 722×261)@ Wikimedia Commons · Dvdgmz(CC BY-SA 4.0)

那 3 个传染性许可仓库为什么值得单列:本篇只讲"清单怎么记它", 不讲"混用合不合法"。清单对它们的处理与宽松许可是一样的—— 都只是"指路 + 记录",并不因为许可类型而做区别对待。这一点与很多人的直觉相反: 清单并不挑许可,它挑的是作者有没有提出排除请求。

5.7 源码链接

  • 两个反例的落档原件:evidence/source/OtisFX__LICENSE、evidence/source/qUINT__README.md
  • 本机探测:evidence/build/ep08_fetch_src.py(平台字段)/ep08_probe_rest2.py(限流补齐)/ep08_readme_license.py(README 复查)
  • GShade 的授权页(逐个文件取得再分发授权的现成案例):https://gshade.org/en/licensing

六、付费墙那一半:为什么连指针都不给

第六章讲边界。这一章只有两个数字,但它们把生态切成了两半。

6.1 读数:免费的刚好是那 4 个

上面的 iMMERSE 包(第 [23] 段)只装了 4 个文件:MartysMods_LAUNCHPAD.fx、MartysMods_MXAO.fx、 MartysMods_SHARPEN.fx、MartysMods_SMAA.fx。四个文件、四个效果,看起来平平无奇——但把这四个名字拿去与作者自己公布的免费档一对,事情就清楚了。 这张图把"清单里的这 4 个"与"付费档的那些"并排摆出来,一并给出三档的价位。

免费子集与付费档:四个免费文件在册,五个付费档名字零命中
图 8-16免费子集与付费档:四个免费文件在册,五个付费档名字零命中@ 官方 EffectPackages.ini(随篇归档,脚本现读)· 计数由脚本现数

作者自己公布的免费档,恰好就是这四个(本机复核作者站点):免费档(Public Shaders iMMERSE)列出 MXAO、Launchpad、Sharpen、Anti Aliasing 四项。清单里的 4 个文件,与免费档的 4 项,一一对上。

6.2 付费档:499 个条目里,零命中

好了,这里是本篇最干脆的一个数字。

上面那四个付费档的名字,我在整份清单里逐个搜过(本机现数):

付费档效果 清单里的命中
ReGrade 0
Solaris 0
ReLight 0
ConvolutionBloom 0
Photon 0
RTGI 1 —— 且只出现在另一个包的描述文字里(adding effect like RTGI and SSAO),不是 EffectFiles

五个付费档效果,499 个文件条目里一个都没有。 而作者站点的档位是明码的(本机复核): 每月 5 美元解锁 RTGI/ReGrade/Solaris 等,每月 9 美元加 ReLight/Convolution Bloom, 每月 20 美元再加测试资格。

6.3 为什么"连指针都没有"这件事比"禁不许转"更硬

注意这两件事的区别:

  • 黑名单(第三章)处理的是"文件在公开仓库里,但作者要求别自动下";
  • 付费档处理的是"文件根本不在公开仓库里"。

对后者,清单能做的只有一件事:不认识它。你不能给一个不存在的东西写指针—— 这就是为什么 499 条里一个付费档文件名都没有。这一节的结论比第三章那条更硬:黑名单处理的是"文件在公开仓库里、但作者要求别自动下",付费档处理的是"文件根本不在公开仓库里";前者的处置是"把它列进名单",后者的处置是"清单里没有这一格"。下面两张图分别给出付费墙这个概念本身,以及这条分割线的位置。

付费墙的机制级实例:内容可见、正文被挡(原图 512×370)
图 8-17付费墙的机制级实例:内容可见、正文被挡(原图 512×370)@ Wikimedia Commons · Baron Maddock(CC BY 4.0)
分割线:清单负责的那一半可自动下载,另一半连指针都没有
图 8-18分割线:清单负责的那一半可自动下载,另一半连指针都没有@ 本系列绘制

6.5 三档价位与三个效果之间,隔着什么

把价位与效果摆在一起看。

把价位与效果摆在一起看,会发现一个分层逻辑(本机复核作者站点):

档位 每月 新增解锁 这类效果的共同点
免费 0 MXAO/Launchpad/Sharpen/Anti Aliasing 单帧、屏幕空间:只看当前这一帧的颜色与深度
Ray Tracer 5 美元 RTGI/ReGrade/Solaris/Depth of Field/Clarity/Exposure Fusion 引入光线传播的近似:成本高一个量级
Path Tracer 9 美元 ReLight/Convolution Bloom + 两个 Addon 要跨帧累积:需要时间维度上的稳定性
Photon Mapper 20 美元 早期版本与测试资格 更重的全局光照近似

免费档恰好是"单帧"那一层,而付费档逐级往"跨帧、全局"走。 这与第六篇讲过的 add-on 面是对得上的:越往全局光照走,越需要更深的运行时干预 (跨帧的历史缓冲、更多的资源视图、甚至 add-on 事件)——那正是作者要把它们放在付费档的技术原因之一。

口径说明:上表最后一列是本机按效果名与档位结构做的归类,不是官方的说法—— 官方页面只列档位与效果名,不解释"为什么这样分"。这一处按归类标注,不当事实陈述。

6.6 源码链接

七、官方自己也要合规:兼容性清单里的 191 次默认修正

第七章回到第一份清单之外的那一份:Compatibility.ini。它看起来与许可无关,其实是同一套合规逻辑的另一面。

7.1 概念:第三份清单管的是"装完之后"

EffectPackages.ini 管"装什么",Addons.ini 管"装哪些附加组件", 而 Compatibility.ini 管的是装完之后该改什么——它按进程名给出一组覆盖设置。

; —— Compatibility.ini 的两段,逐字 ——
# A Hat In Time
[HatinTimeGame.exe]
RenderApi=D3D9

# A Plague Tale: Innocence
[APlagueTaleInnocence_x64.exe]
RenderApi=D3D11
DepthReversed=1
DepthCopyBeforeClears=1

7.2 读数:288 个进程、582 行设置

先来看看这份清单里到底写了什么。它的写法有两种:一种是只指定图形接口(一行就够),另一种是在接口之外再叠几项深度修正;后者才是这一章的主角,因为那几个键与第七篇讲过的配置键同名。下面这张图给出逐键的出现次数。

兼容性清单的读数:288 个进程段、DepthReversed 出现 191 次
图 8-19兼容性清单的读数:288 个进程段、DepthReversed 出现 191 次@ 官方 Compatibility.ini(随篇归档,脚本现读)· 计数由脚本现数
键 次数 与第七篇的关系
RenderApi 237 指定该进程用哪个图形接口
DepthReversed 191 第七篇 [DEPTH] 段的同名键
Banned 56 键名示意"不允许安装",但清单里没有注释解释语义(见 7.4)
DepthCopyBeforeClears 54 [DEPTH] 段的同名键
DepthUpsideDown 21 同一族(上下颠倒修正)
UseAspectRatioHeuristics 7 [DEPTH] 段的同名键
InstallTarget 6 安装目标形态
ForceInstallApi 3 强制指定接口
DepthCopyAtClearIndex 3 [DEPTH] 段的同名键
DrawStatsHeuristic 2 [DEPTH] 段的同名键

7.3 与第七篇接口:旋钮的另一半

第七篇里,ReShade.ini 的 [DEPTH] 段那 8 个配置键被讲成"用户能拧的旋钮"—— 当时给出的结论是"这套检测器把复杂度压到 8 个键,其余全靠自适应"。

而这份清单补上了另一半事实:官方自己在一款一款地替你拧。 DepthReversed 出现 191 次就是 191 个进程的默认修正; DepthCopyBeforeClears 54 次、DepthUpsideDown 21 次,同样如此。

这两篇由此接上:第七篇说"深度时灵时不灵"有四道条件,其中第四道是"检测算法与子矩形的冲突"; 这份清单说明官方对这个冲突的处置方式不是改算法,而是逐进程写例外—— 与第七篇查到的那四个具名游戏补丁(Mirror's Edge/Portal/Mass Effect 3 (LE)/Garry's Mod) 是同一个思路的两种规模:一个写在源码里,一个写在清单里。

7.4 一处只给键名、不给语义的地方

上表里有一行我特意标了"没有注释解释语义":Banned,出现 56 次,取值一律是 1。

; —— 该键的逐字形态 ——
Banned=1

这一处本机只能给出键名与计数。 清单里的 247 行注释全是游戏名, 没有任何一行解释这个键的语义;官方文档里本轮也没有查到对应的说明。 所以正文不猜它的含义——"测不了就写测不了",这是本系列一贯的处置。

顺便把本篇的证据分级说清楚,因为它决定了每一句话能说多重:

级别 长什么样 本篇的用法
一级:原件逐字 我自己抓下来、能贴出原文的 清单片段、许可正文、论坛规则——可以直接引用
二级:本机现数 脚本对原件解析出来的数字 45/499/20/191 这些——可以断言,且注明脚本
三级:本机归类 我按结构做的归类与推断 六.5 那张"档位与效果类型"的表——必须标注为归类
不入级 二手转述、社区传话 只在 material-inventory.md 里当背景,不单独作为论据

这张表比结论重要:同一篇里的每句话,读者应该能一眼看出它站在哪一级上。 凡是标了"归类"的,都可以被推翻;凡是一级的,都得先推翻原件才行。

7.6 逐进程清单里的三段原文

下面进入原文。

把这份清单摊开看三段原文,比任何描述都清楚(本机现数,逐字):

; —— 第一段:只要接口,不要别的 ——
# A Hat In Time
[HatinTimeGame.exe]
RenderApi=D3D9

; —— 第二段:要接口,还要两项深度修正 ——
# A Plague Tale: Innocence
[APlagueTaleInnocence_x64.exe]
RenderApi=D3D11
DepthReversed=1
DepthCopyBeforeClears=1

; —— 第三段:同一款游戏的两个可执行文件各写一段 ——
[ApexLauncher.exe]
RenderApi=D3D11
…
[r5apex.exe]
RenderApi=D3D11
…(另有一行单独的 Banned=1,见 7.4 的说明)

三段原文说明三件事:

  1. 粒度是"可执行文件",不是"游戏"。上例里 Apex 有启动器与主程序两个进程, 清单里是两段——因为它匹配的是进程名,不是标题名。
  2. 默认设置可以少到只有一行。第一段只有 RenderApi=D3D9: 对大部分游戏来说,官方的"兼容性"只需要指定接口,其余什么都不改。
  3. 需要改深度的进程是少数。DepthReversed 191 次看着多,但放在 288 个进程段里是三分之二不到; 真正需要"清空前先拷一份"的(DepthCopyBeforeClears)只有 54 个进程。

7.7 与第七篇的接口汇总

把两篇的读数并到一处,这张对照表就是"旋钮的两半":

读数的位置 谁在拧 证据
ReShade.ini 的 [DEPTH] 段 8 个键 用户(可以在界面里手改) 第七篇第一章:8 个配置键逐条
同一批键的默认值 官方(逐进程写进清单) 本篇第七节:DepthReversed 191 次等
源码里的四个具名游戏补丁 开发者(写死在检测器里) 第七篇第五章:Mirror's Edge/Portal/ME3 (LE)/Garry's Mod

三层都在做同一件事:把"通用算法覆盖不到的情况"逐条记下来。 区别只在记录的位置——写死在源码里、写进清单里、还是留给用户自己试。

7.8 源码链接

八、三方视角与两处"清单没说"

第八章把镜头拉远:同一件事,三方各自该做什么;再老实交代两处清单没说的事。

8.1 三方视角:作者、使用者、宿主

三方各自该做什么:作者声明,使用者只发预设,宿主指路不托管
图 8-20三方各自该做什么:作者声明,使用者只发预设,宿主指路不托管@ 本系列绘制
角色 该做的事 依据(本机复核过的原文)
作者 明确声明许可;对个别文件提出"别自动下载"的请求 清单的 DenyEffectFiles 就是这条请求的落点(第三章 20 个文件)
使用者 只发预设(.ini),不打包任何 shader 官方论坛规则:Your personal distribution may only include A - your modified configuration files (.cfg…) B - your personally implemented shader files;Marty's Mods 指南:You cannot include the shader files in your preset package
宿主 指路、不托管;把排除请求落进安装器 45/45 全是指针(第二章);官网下载区:Do NOT share the binaries or shader files. Link users to this website instead.

三方之中,只有"宿主"这一侧是工程活:另外两方都是"要不要这么做"的选择, 而宿主要把所有人的意愿变成可执行的行为——这就是那两张名单存在的理由。

8.2 两处"清单没说"之一:6 个整包被注释掉了

附加组件清单里被整包注释掉的六段(26 个包里的 6 个)
图 8-21附加组件清单里被整包注释掉的六段(26 个包里的 6 个)@ 官方 Addons.ini(随篇归档,脚本现读)

Addons.ini 有 26 个包,其中 6 个整包被注释符注释掉(本机现数,逐字):

# PackageName=Framerate Limiter by crosire
# PackageName=Shader Dump by crosire
# PackageName=Shader Replace by crosire
# PackageName=Texture Dump by crosire
# PackageName=Texture Replace by crosire
# PackageName=Texture Overlay by crosire

这 6 个包有一个共同点:作者全是 crosire 自己。 而它们的名字与主仓库顶层那 6 个示例目录同名 (01-framerate_limit/05-shader_dump/06-shader_replace/07-texture_dump/ 08-texture_replace/10-texture_overlay,本机在仓库清单里读到的目录名)。

为什么被注释掉?清单没说。 没有注释、没有提交说明、官方文档里也没写。 所以这一处只陈述事实(6 个整包被注释、全是作者自己的),原因不作推断—— 这也是本篇第 7.4 节同一条纪律的第二次应用。

8.3 两处"清单没说"之二:这份生态的外部供给实况

素材供给的实况:188 条候选里题域外占 68.6%,两个概念图零命中
图 8-22素材供给的实况:188 条候选里题域外占 68.6%,两个概念图零命中@ 本篇素材候选池检索记录(随篇归档,脚本现读)

这一节的数字来自本篇自己的素材检索(10 轮留痕,见 search-log.jsonl):

读数 值
候选池 188 条
题域外(古籍扫描、行业报告 PDF、同名不同义的实拍) 129 条 = 68.6%
题域内且可用的方向 5 类(许可谱系/类型着色/兼容表/传染链/付费墙实例)
"软件再分发"概念的专门示意图 0 条
"禁止再分发"概念的专门示意图 0 条

先来说说这张图为什么放在结论之前:它决定了本篇能证明什么、不能证明什么。 "这一份清单里有七种许可状态"这句话,证据只能来自本机对清单与仓库的现读—— 公开素材里没有一张图能替你证明它。这也是本篇 24 个点位里有 11 位是"本机与源码读数面板"的原因。

8.4 一份很短的时间线(口径:官方公开可核的日期)

日期 事件 来源
2017-01-01 ReShade 本体开源,采用 BSD 3-clause 官网首页(本机复核)
2015 年前后 论坛《Distribution Regulations》确立"预设可发、shader 不要打包"的规则 ReShade 论坛(本机复核)
2026-08-02 当前版本 6.8.0 发布 官网下载区(本机复核)

口径说明:这张表只收官方公开可核的三个日期;论坛那两条规则的最初发布日期 在页面上显示为相对时间("11 年前"),没有精确日期——不猜,按相对口径写。

8.5 三方依据的原文(本机复核)

8.1 那张表里的三条依据,我逐字抄下来,方便对照:

第一条 · ReShade 官方论坛《Distribution Regulations》(本机核过页面):

Your personal distribution may only include A - your modified configuration files (.cfg in the \ReShade folder) B - your personally implemented shader files

If you want to modify and distribute existing files other than configuration files (.cfg in the \ReShade folder) A - Ask the original developer here at ReShade.me for permission to do so B - Request the change to be implemented by the original developer here at ReShade.me

第二条 · iMMERSE 作者的官方指南(本机复核):

Free Shaders with Redistribution Restrictions —— Many free shaders, even those available on GitHub or other open platforms, have licenses that prohibit redistribution. This means: You cannot include the shader files in your preset package.

Common examples include shaders from: Marty's Mods (iMMERSE, METEOR collections). qUINT shaders.

Never redistribute paid shaders - This violates copyright and the terms of service.

第三条 · GShade 的授权页:它走的是最重的那条路——逐个文件取得书面授权。 页面逐文件列出取得授权的 shader、纹理与预设(其中就有 MartysMods_*.fx 与 qUINT_*.fx 那一族), 并在页首写明理由:whose licenses or copyrights otherwise do not allow for redistribution, re-hosting, or automated downloading。

两条规矩放在一起看,分工很清楚:论坛那条讲"想改别人的东西怎么办"(去问作者), 作者指南那条讲"想分享自己的配置怎么办"(只发 .ini)。两种做法合起来覆盖了使用者的两种动作。

三种做法的成本对照:

做法 谁在用 成本
只发预设(不碰 shader) 论坛规则与作者指南都推荐 最低——不需要任何授权
指路 + 尊重排除请求 这一份清单 低——但要维护两张名单
逐个文件取得授权 GShade 这类整合发行版 最高——要一个个联系作者并留档

8.6 一处"别人的做法"值得记一笔

GShade 那一页还有一句值得引:它把"再分发、重新托管、自动化下载"并列成三件事, 并说明自己对这三件事都取得了授权。

这句话解释了为什么这份官方清单要设计成"指路":它连"自动化下载"都不想越界—— 所以它不托管、只给坐标,并且把作者点名的文件放进黑名单。 合规章,在工程上的样子就是这两张名单。

8.7 顺带一处发现:同一个仓库的另一个分支

查这一篇的资料时还注意到一件事,值得记一笔:reshade-shaders 这个仓库不止一个分支。

  • list 分支:三份清单(本篇第一到三、七章的主角);
  • slim 分支:一组精简效果(Standard effects 包就装它的快照);
  • legacy 分支:上一代 ReShade 的效果(Legacy effects 包)。

而第三篇讲过的着色语言参考 REFERENCE.md,就在这个仓库的 slim 分支上 (官网原文给的链接逐字是 github.com/crosire/reshade-shaders/blob/slim/REFERENCE.md)。

这一处小发现说明一件事:这个仓库承担了三种角色——清单位置、效果存放位置、语言文档位置。 但它们在三个不同的分支上,各自独立演进。一个仓库,三种身份, 这也解释了为什么"官方生态"这件事很难一句话说清:它本来就不是一个地方。

8.8 一处没做的实验,以及为什么

到这里,八章讲完了,但有一类问题本篇刻意没有碰:那些效果装上去到底什么感受。

原因不是做不到,而是分工:第九篇要在自有开源 demo 上把这一整套装起来逐效果做前后对比,第十篇再算帧耗账。如果本篇也去跑实验,就会出现两张口径不同的"效果清单"——一张来自清单里的元数据,一张来自实际跑出来的画面。两张都对,但混在一起讲就没法核对了。

所以本篇的每一个数字都能指向一个文件或一个 API 返回,一个都不来自"我看着差不多"。

九、结论与路线图

9.1 三条结论

三条结论与它们各自的判据
图 8-23三条结论与它们各自的判据@ 本系列绘制
  1. 这份清单是指针,不是仓库。 45 个包全部带指向作者仓库的地址,下载地址也全部落在同一个宿主上。 判据:RepositoryUrl 45/45、同宿主 45/45、指向非 github 的 0 个。
  2. "装什么"由两张名单定,而且黑名单优先。 白名单 499 条逐文件点名,黑名单 20 个文件分布在 8 个包; 实测 3 个包里同一个文件既列白名单又被排除 ⇒ 黑名单覆盖白名单。
  3. 同一份清单里有七种许可状态。 其中最大的一格不是"宽松"也不是"专有",而是 "既没有许可文件、README 也没声明"的 10 个仓库——它占 44 个仓库的将近四分之一。 判据:44 个仓库逐条的字段 + 文件 + README 三级复核。

9.2 三类读者的最短路径

  • 只想知道"我能不能把一个 shader 打包进我的预设":读第三章与第八章第一节。 答案只有一句——只发 .ini,别打包 shader;
  • 想知道"某个效果能不能改、能不能转":读第五章。先看它有没有许可文件,再看 README,最后看源文件注释—— 字段只能给你下限;
  • 想搞清楚"官方生态到底怎么运转":读第一、二、三章。入口是三份 INI, 机制是"指路 + 两张名单",边界是"付费档连名字都不出现"。

9.3 三条结论各自怎么复核

结论要能复核。

结论必须能复核,否则它只是观点。三条结论的复核路径如下:

结论 复核命令 期望
45 个包全是指针 python evidence/build/ep08_fetch_src.py 打印 45 个包 | 有 RepositoryUrl 45 | 有 DownloadUrl 45,且宿主统计里"非 github 的包:无"
白名单 499、黑名单 20、3 个包重叠 python evidence/build/ep08_derive.py 打印 EffectFiles 条目 499(去重 499)、DenyEffectFiles 21 处(去重 20,落在 8 个包),以及交集那三个包
七种许可状态 python evidence/build/ep08_license_map.py 打印七个类别的仓库计数:MIT 15/BSD 3/CC0 2/GPL-2.0 2/GPL-3.0 1/有文件未识别 6/README 声明 3/无文件未声明 10/自定义专有 1/待归类 1

这三条命令跑出来的是同一份数字。 若有一天清单更新了,重跑即可—— 本篇没有一处结论依赖"我记得它大概是这样的"。

9.4 一个具体问题走一遍

最后回答那个评论区里最常被问的问题,按本篇的逻辑走一遍:

"我想把一个别人的 shader 打包进我的预设,行不行?"

第一步:先看有没有许可文件。 去那个 shader 的仓库根目录找 LICENSE/LICENSE.md/LICENSE.txt/COPYING。

第二步:有文件就读正文,没有就看 README。 如果限定了"再分发"(prohibition of redistribution、 "不允许公开传播"之类的措辞),答案就是不行;如果 README 里也没有声明,按默认规则处理—— 那是保留所有权利。

第三步:不管结论如何,最后一句话都是一样的。 这也是官方论坛那条规则给出的操作口径:

只发预设(.ini),不要打包 shader 文件;需要 shader 的人,让他自己去原站下载。

为什么第三步可以"一票决定":因为预设文件(.cfg/.ini)是你自己的配置, 而 shader 是别人的作品。这条界线与许可类型无关,与作者脾气也无关—— 它只需要你分清"哪些字节是自己写的"。

把本篇收成一句:这份清单能在同一份文件里装下七种许可状态, 不是因为谁宽容,而是因为它从头到尾只做了两件事——指路,和记住谁的意愿是什么。

本篇把 45 个包、44 个仓库与三份清单都数了一遍。有查错的地方,欢迎在评论区指出来——这份清单随时会变,本篇的读法也该跟着变。

9.5 与后面几篇的接口

  • 第九篇(自跑一):把这一篇的"能不能用"落到"实际装上是什么样"——在自有开源 demo 上逐效果跑前后对比。 届时只会用到清单里许可清晰、可自由使用的那些效果;
  • 第十篇(自跑二):效果栈与帧耗账,外加自己写一个小 .fx——那时会回到第三篇的着色语言;
  • 第十一篇(合集):把十一篇的账并到一处,这一篇的"七种许可状态"与"两张名单"会作为 工程取舍的一节被引用。

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

下面这张表是本篇所有数字的汇总,每一行都能重跑脚本复现(脚本名在最后一列)。 列在这儿的目的是:如果哪天清单更新了,照着这张表重跑一遍就知道哪一行的结论变了。

# 读数 值 出处脚本
1 效果包清单规模 415 行 / 25,198 字节 ep08_fetch_src.py
2 附加组件清单规模 210 行 / 13,164 字节(非空 179 行) ep08_fetch_lists.py
3 兼容性清单规模 1,364 行 / 20,320 字节 ep08_fetch_lists.py
4 效果包数 45 ep08_fetch_src.py
5 附加组件包数 26(含 6 个整包被注释) ep08_fetch_lists.py
6 兼容性清单的进程段 288(段名全是进程名) ep08_verify_compat.py
7 仓库所有者数 41 ep08_fetch_src.py
8 .fx 条目 499(去重后仍是 499) ep08_fetch_src.py
9 带 RepositoryUrl 的包 45 / 45 ep08_fetch_src.py
10 下载地址与仓库同宿主 45 / 45 ep08_derive.py
11 下载地址指向官方自己仓库 2(Standard effects、Legacy effects) ep08_derive.py
12 带 DenyEffectFiles 的包 8(共 21 处、去重 20 个文件) ep08_fetch_src.py
13 黑名单与白名单重叠的包 3(FXShaders 1、Daodan 1、RSRetroArch 7) ep08_derive.py
14 条目最多的包 71(RSRetroArch) ep08_derive.py
15 条目最少的包 6 个包各 1 条 ep08_derive.py
16 许可探测的仓库数 44 ep08_license_map.py
17 宽松许可仓库 20(MIT 15 / BSD-3 3 / CC0 2) ep08_license_map.py
18 传染性许可仓库 3(GPL-2.0 2 / GPL-3.0 1) ep08_license_map.py
19 有许可文件但机器认不出 6 ep08_license_map.py
20 无许可文件但 README 有声明 3 ep08_readme_license.py
21 无许可文件、README 也无声明 10 ep08_readme_license.py
22 被平台限流(403)的探测 7(全部改用 jsdelivr 补齐) ep08_fetch_src.py
23 付费档文件名在清单里的命中 0(RTGI 仅出现在别包的描述文字里) ep08_derive.py
24 兼容性清单的深度相关键 DepthReversed 191 / DepthCopyBeforeClears 54 / DepthUpsideDown 21 / UseAspectRatioHeuristics 7 / DepthCopyAtClearIndex 3 / DrawStatsHeuristic 2 ep08_fetch_lists.py
25 外部素材候选池 188 条(题域外 129 条 = 68.6%) ep08_screen_pool.py
26 本次验证的日期 2026-10-11(清单与原件的抓取日) 各脚本的落档时间

相关链接与参考资料

官方清单与文件(本篇的一手材料)

规则与出处

许可原件(随篇归档,可复核)

  • ReShade 本体许可(BSD-3-Clause):evidence/source/reshade__LICENSE
  • iMMERSE 的自定义专有许可:evidence/source/iMMERSE__LICENSE
  • qUINT 的 README(许可写在 README 里):evidence/source/qUINT__README.md
  • OtisFX 的 MIT 许可(机器认不出的那一份):evidence/source/OtisFX__LICENSE
  • SweetFX 的 MIT 许可:evidence/source/SweetFX__LICENSE

本篇点名过的仓库(想自己核许可的,按这张表逐个去看)

仓库 本篇的许可结论 地址
crosire/reshade-shaders 未见许可文件、README 也无声明 https://github.com/crosire/reshade-shaders
CeeJayDK/SweetFX MIT(黑名单 1 项) https://github.com/CeeJayDK/SweetFX
FransBouma/OtisFX MIT(机器认不出那一个) https://github.com/FransBouma/OtisFX
martymcmodding/qUINT README 声明:保留所有权利 https://github.com/martymcmodding/qUINT
martymcmodding/iMMERSE 自定义专有(禁止公开传播) https://github.com/martymcmodding/iMMERSE
martymcmodding/METEOR 有许可文件、机器未识别 https://github.com/martymcmodding/METEOR
luluco250/FXShaders MIT(黑名单 1 项、且与白名单重叠) https://github.com/luluco250/FXShaders
Daodan317081/reshade-shaders BSD-3-Clause https://github.com/Daodan317081/reshade-shaders
LordOfLunacy/Insane-Shaders CC0-1.0 https://github.com/LordOfLunacy/Insane-Shaders
originalnicodr/CorgiFX CC0-1.0 https://github.com/originalnicodr/CorgiFX
BlueSkyDefender/AstrayFX 未见许可文件、README 也无声明 https://github.com/BlueSkyDefender/AstrayFX
Matsilagi/RSRetroArch 未见许可文件、README 也无声明 https://github.com/Matsilagi/RSRetroArch
LordKobra/CobraFX MIT(黑名单 1 项) https://github.com/LordKobra/CobraFX
liuxd17thu/BX-Shade 未见许可文件、README 也无声明 https://github.com/liuxd17thu/BX-Shade
umar-afzaal/LumeniteFX 自定义专有(AGNYA License) https://github.com/umar-afzaal/LumeniteFX
AlucardDH/dh-reshade-shaders GPL-2.0 https://github.com/AlucardDH/dh-reshade-shaders
akgunter/crt-royale-reshade GPL-2.0 https://github.com/akgunter/crt-royale-reshade
EndlesslyFlowering/ReShade_HDR_shaders GPL-3.0 https://github.com/EndlesslyFlowering/ReShade_HDR_shaders

本机取证脚本(本篇所有数字的出处)

  • evidence/build/ep08_fetch_src.py — 抓三份清单与关键许可原件、45 条许可探测
  • evidence/build/ep08_probe_rest2.py — 补齐被平台限流的 7 个仓库
  • evidence/build/ep08_readme_license.py — 无许可文件者再查 README 声明
  • evidence/build/ep08_fetch_lists.py / ep08_verify_compat.py — 另两份清单的解析
  • evidence/build/ep08_license_map.py / ep08_derive.py / ep08_screen_pool.py

下篇预告

下一篇(第九篇)进入"自跑":在一个自有开源 D3D11 demo 上把 ReShade 装起来,逐效果做前后对比。 本篇讲的是"哪些效果可以用、怎么找到它们、用的时候要注意什么"; 下一篇就按这份清单真的装一遍——包括"装完之后那些兼容性设置到底改了什么"。

两篇之间会有一个交叉验证:本篇第七节里 DepthReversed 那 191 次默认修正, 到时候会挑其中一款在 demo 上手工复现一次,看它到底改变了什么。

写在最后

本篇没有跑一次游戏,也没有写一行 shader。它只是把一份清单读了 44 遍。

写它的时候有两次想"算了吧":一次是发现 45 条探测里有 7 条被平台限流, 差点就把那 7 个记成"没有许可";另一次是发现"完全未声明"竟然有 10 个仓库—— 比任何一类明确许可的仓库都多。两次都是同一个教训:机器给的结论只能当下限用。

如果本篇只能留一句,我希望是这句:"能不能转"的答案不在许可条款的比较表里, 而在"这份清单有没有托管任何东西"这个形态问题上。 它没有——所以它才能同时装下这七种状态。

如果你正好在做一套预设、或者想把自己改的效果发出去,希望能对大家有所帮助—— 把它先当成一个形态问题看,比背许可条款管用。