画面エフェクトパック

画面全体にかかるポストプロセスパック (API 3): 色収差、フィルムグレイン、CRTなど。マニフェスト項目、PackEffect、ステージ、エフェクトスタック、オンラインギャラリー。

エフェクトパックとは

サーフェスパックは1体のキャラクターのマテリアルのシェーディングを置き換えます。エフェクトパック ("type": "effect") は代わりに完成したフレーム全体に働きます。色収差、フィルムグレイン、CRT走査線、グリッチ、独自のビネットなどです。エフェクトはモデルではなく画面全体に属します。

エフェクトはアプリに同梱されていません。シェーダータブのオンライン一覧 (ギャラリー) からインストールするか、zipを取り込んでください。現在ギャラリーには chromatic_aberration、film_grain、crt_scanlines があります。エフェクトパックには MMDX12 1.4.0 以降 (APIバージョン3) が必要です。

エフェクトを使う

  1. シェーダータブのオンライン一覧からエフェクトパックをインストールします。
  2. ロビーのシェーダータブで画面エフェクトの行を開くか、再生バーのキラキラボタンを押します。
  3. 使うエフェクトをオンにし、矢印で順番を変え、スライダーを調整します。

スタックは最終画像に上から下へ実行されます。再生画面、ロビーのプレビュー、リアルタイムの動画・静止画レンダー (ラスター、リアルタイムRT、リアルタイムPT) に適用されます。オフラインGIレンダラー、アンリット・ワイヤーフレーム表示、スタジオの4分割ビューには適用されません。有効なエフェクトがなければ追加のターゲットもパスもなく、この機能のないビルドと同一のフレームになります。

コマンドラインでは --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": { "ja": "フィルムグレイン", "en": "Film grain" },
  "params": [
    { "key": "strength", "label": { "ja": "強さ", "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グロー向き、露出を考慮するエフェクト

両方のステージのエフェクトを1つのスタックに混在できます。各ステージは自分のエフェクトだけをスタック順に実行します。

effect.hlsl

パックは関数を1つ実装します。

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

PackEffectInput のフィールド:

フィールド意味
uvテクセル中心、0..1、左上 = (0, 0)
pixelSV_Position.xy (ピクセル)
outputSize出力解像度 (ピクセル)
timeシーン開始からの秒数
frameIndexフレームカウンター (64で循環)
colorこのピクセルのここまでの画面 (アルファ保持)
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" を指定してください。