画面特效包

作用于整个画面的后处理包 (API 3):色差、胶片颗粒、CRT 等。清单字段、PackEffect、阶段、特效栈与在线图库。

什么是特效包

表面包 (surface) 替换单个角色材质的着色。特效包 ("type": "effect") 则作用于已完成的整个画面:色差、胶片颗粒、CRT 扫描线、故障效果、自定义暗角等。特效属于整个画面,而不是某个模型。

特效不随应用内置。请在着色器标签页的在线列表 (图库) 中安装,或导入 zip。图库目前提供 chromatic_aberration、film_grain 和 crt_scanlines。特效包需要 MMDX12 1.4.0 或更高版本 (API 版本 3)。

使用特效

  1. 在着色器标签页的在线列表中安装特效包。
  2. 在大厅的着色器标签页展开画面效果一行,或点击播放栏上的闪光按钮。
  3. 启用需要的特效,用箭头调整顺序,并调节滑块。

特效栈对最终图像从上到下依次执行,适用于播放画面、大厅预览以及实时视频和静帧渲染 (光栅、实时 RT、实时 PT)。不适用于离线 GI 渲染器、无光照和线框视图以及工作室的四视图。没有启用任何特效时,不会创建额外的渲染目标和渲染通道,画面与没有此功能的版本完全相同。

命令行中,--effect <id>[,<id>...] 在单次运行中替换特效栈,--effect none 清空。

文件夹结构

my_effect/
  pack.json      清单 (与表面包相同的字段 + type / stage)
  effect.hlsl    实现 PackEffect
  preview.png    可选,建议 16:9
  textures/      可选,pack.json 的 "textures" (规则与表面包相同)

清单新增项

{
  "format": 1,
  "id": "film_grain",
  "version": "1.0.0",
  "apiVersion": 3,
  "minAppVersion": "1.4.0",
  "type": "effect",
  "stage": "post",
  "name": { "zh": "胶片颗粒", "en": "Film grain" },
  "params": [
    { "key": "strength", "label": { "zh": "强度", "en": "Strength" }, "default": 0.12, "min": 0.0, "max": 0.6 }
  ]
}
  • "type": "effect" 表示特效包 (默认为 "surface")。
  • "stage" 为 "post" (默认) 或 "pre-bloom"。
  • 不使用 classes。params (最多 16 个) 和 textures (最多 16 个) 与表面包的行为完全相同,参见清单。
stage输入与输出用途
post色调映射和颜色 LUT 之后的显示 sRGB,8 位颗粒、扫描线、镜头色边、暗角
pre-bloom泛光之前的线性 HDR RGBA16F适合辉光或与曝光相关的特效

两个阶段的特效可以放在同一个栈中,每个阶段只按栈顺序运行属于自己的特效。

effect.hlsl

特效包实现一个函数:

float3 PackEffect(PackEffectInput i) { return i.color.rgb; }

PackEffectInput 字段:

字段含义
uv纹素中心,0..1,左上角 = (0, 0)
pixelSV_Position.xy (像素)
outputSize输出分辨率 (像素)
time场景开始后的秒数
frameIndex帧计数器 (到 64 回绕)
color此像素到目前为止的画面 (保留 alpha)
depth原始设备深度,1 = 背景 (用 LinearZ() 转换)
normal世界空间法线,背景处未定义
motion运动向量,uv(当前) - uv(上一帧)

辅助函数:

  • gEffectSource.SampleLevel(gLinear, uv, 0) 读取到目前为止画面的任意像素 (双线性、钳制)。镜头类特效就是这样查看周围像素的。
  • PackParam(i) 按 pack.json 顺序返回第 i 个参数的滑块值 (或默认值)。
  • PackFxSampleTex(i, uv)、PackFxSampleTexLevel、PackFxTexSize、PackFxTexCount 用于采样包内纹理。sRGB 纹理返回线性值。
  • common.hlsli 中的全部内容:Luminance、LinearZ、Ign、SrgbToLinear、gTime 等。

line 是 HLSL 的保留字。

示例:色差

float3 PackEffect(PackEffectInput i) {
    const float2 dir = i.uv - 0.5;
    const float r = length(dir) * 1.41421356;   // 中心为 0,角落为 1
    const float2 offset = dir * (PackParam(0) * 0.03 * pow(r, PackParam(1)));
    float3 c;
    c.r = gEffectSource.SampleLevel(gLinear, i.uv + offset, 0).r;
    c.g = i.color.g;
    c.b = gEffectSource.SampleLevel(gLinear, i.uv - offset, 0).b;
    return c;
}

红色和蓝色沿远离画面中心的方向采样,越靠近边缘偏移越大。

编译与调试

着色器在运行时用 DXC (ps_6_0) 编译。编译错误会跳过该特效,在 mmdx12.log 写入 [E] 行,并通过提示和着色器管理器中的状态告知,不会崩溃。应用运行时保存 effect.hlsl 会自动重新加载。

命令行可用 pack_check <文件夹|zip> --compile 检查,参见调试。发行版的 shaders/pack_template_effect 可作为起点。

发布

特效包与表面包使用相同的 zip 结构、版本和审核规则,参见发布。由于 API 版本为 3,请设置 "minAppVersion": "1.4.0"。