Screen Effect Packs
Whole-screen post-processing packs (API 3): chromatic aberration, film grain, CRT and your own. Manifest fields, PackEffect, stages, the effect stack and the online gallery.
What an Effect Pack Is
A surface pack replaces the shading of one character’s materials. An effect pack ("type": "effect") works on the finished frame instead: chromatic aberration, film grain, CRT scanlines, glitch, a custom vignette. Effects belong to the whole picture, not to a model.
Effects are not bundled with the app. Install them from the online gallery (the “Shaders” tab, online list) or import a zip. The gallery currently offers chromatic_aberration, film_grain and crt_scanlines. Effect packs need MMDX12 1.4.0 or newer (API version 3).
Using Effects
- Install an effect pack from the online list of the Shaders tab.
- Open the lobby’s Shaders tab and expand the Screen effects row, or press the sparkle button on the play bar.
- Enable the effects you want, change their order with the arrows and tune their sliders.
The stack runs top to bottom on the final image. It applies to play mode, the lobby preview and the real-time video and still renders (raster, real-time RT, real-time PT). It does not apply to the offline GI renderer, the unlit and wireframe views or the Studio quad view. With no effect enabled the frame is identical to one rendered without the feature: no extra targets, no extra passes.
From the command line, --effect <id>[,<id>...] replaces the stack for one run and --effect none clears it.
Folder Layout
my_effect/
pack.json manifest (same fields as surface packs, plus type / stage)
effect.hlsl implements PackEffect
preview.png optional, 16:9 recommended
textures/ optional, pack.json "textures" (same rules as surface packs)
Manifest Additions
{
"format": 1,
"id": "film_grain",
"version": "1.0.0",
"apiVersion": 3,
"minAppVersion": "1.4.0",
"type": "effect",
"stage": "post",
"name": { "ko": "필름 그레인", "en": "Film grain" },
"params": [
{ "key": "strength", "label": { "en": "Strength" }, "default": 0.12, "min": 0.0, "max": 0.6 }
]
}
"type": "effect"selects an effect pack ("surface"is the default)."stage"is"post"(default) or"pre-bloom".classesare not used.params(at most 16) andtextures(at most 16) work exactly like in surface packs, see Manifest.
| stage | input and output | use for |
|---|---|---|
post | display-referred sRGB after tonemap and colour LUT, 8-bit | grain, scanlines, lens fringes, vignette |
pre-bloom | linear HDR RGBA16F, before the bloom | glow-friendly or exposure-aware effects |
Effects of both stages can sit in one stack. Each stage runs its own effects in stack order.
effect.hlsl
A pack implements one function:
float3 PackEffect(PackEffectInput i) { return i.color.rgb; }
PackEffectInput fields:
| field | meaning |
|---|---|
uv | texel centre, 0..1, top left = (0, 0) |
pixel | SV_Position.xy in pixels |
outputSize | output resolution in pixels |
time | seconds since the scene started |
frameIndex | frame counter (wraps at 64) |
color | the frame so far at this pixel (alpha kept) |
depth | raw device depth, 1 = background (LinearZ() converts it) |
normal | world-space normal, undefined on the background |
motion | motion vector, uv(current) - uv(previous) |
Helpers:
gEffectSource.SampleLevel(gLinear, uv, 0)reads any pixel of the frame so far (bilinear, clamped). This is how lens effects look around the current pixel.PackParam(i)returns the slider value (or manifest default) of parameteri, inpack.jsonorder.PackFxSampleTex(i, uv),PackFxSampleTexLevel,PackFxTexSize,PackFxTexCountsample the pack’s textures. sRGB textures return linear values.- Everything in
common.hlsli:Luminance,LinearZ,Ign,SrgbToLinear,gTimeand so on.
line is a reserved word in HLSL.
Example: Chromatic Aberration
float3 PackEffect(PackEffectInput i) {
const float2 dir = i.uv - 0.5;
const float r = length(dir) * 1.41421356; // 0 at the centre, 1 in the corners
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;
}
Red and blue are sampled along the direction away from the screen centre, and the offset grows towards the edges.
Compiling and Debugging
The shader is compiled at runtime with DXC (ps_6_0). A compile error skips the effect, writes an [E] line to mmdx12.log, shows a toast and a status in the shader manager. It never crashes. Saving effect.hlsl while the app runs reloads it.
Check a pack from the command line with pack_check <folder|zip> --compile, see Debugging. The release ships a starting point in shaders/pack_template_effect.
Publishing
Effect packs use the same zip layout, versioning and review rules as surface packs, see Publishing. Set "minAppVersion": "1.4.0" because the API version is 3.