コーデック シェーダ
TSMP コーデック シェーダーは、ペイロード バイトと可視フレーム ピクセルの間で変換を行います。デフォルトの Luma4 コーデックは参照パスとして使用できますが、カスタム コーデックは独自のマテリアルとシェーダー パスを使用できます。
エンコード側
エンコード シェーダまたはマテリアルは通常、次のものを受け取ります。
| 入力 | 目的 |
|---|---|
| ペイロード バイト テクスチャまたはバッファ テクスチャ | エンコーダによって配置されたソース バイト。 |
| ヘッダーピクセル | ヘッダー領域はコア エンコーダーによってすでに準備されています。 |
| コーデックオプションバイト | コーデック固有の小さな設定。 |
| ブロックサイズ | シンボル出力のピクセル ブロックの寸法。 |
| ペイロードサイズ | 描画する有効なバイト数。 |
エンコード結果は、ヘッダーを読み取り可能な状態にし、コーデックによって報告されたレイアウトにペイロード シンボルを配置する必要があります。
デコード側
デコード シェーダまたはマテリアルは通常、以下を受け取ります。
| 入力 | 目的 |
|---|---|
| ソース TSMP フレーム | カメラ、OBS、Spout、または別のパスからキャプチャされたテクスチャ。 |
| ヘッダーのメタデータ | ペイロード サイズ、ブロック サイズ、サンプル サイズ、およびコーデック オプション バイト。 |
| ペイロードのレイアウト | 開始行/ブロックとブロック数。 |
| バイト出力テクスチャ | リードバックのために回復されたバイトを保存するテクスチャ。 |
デコーダはヘッダーからペイロードのバイト数のみを読み取ります。未使用のピクセルは結果に影響を与えません。
回復されたバイトを RGBA バイト テクスチャに出力するデコード シェーダについては、TSMPDecodeByteOutput.cginc スクリプト API を参照してください。
準備シェーダーとバイトシェーダー
LUT を使うコーデックには、異なる二つの出力があります。
| パス | 出力 | 意味 |
|---|---|---|
| 準備 | 1行の linear ARGBFloat LUT | 測定したキャリブレーション値。バイトではありません。 |
| バイトデコード | RGBA バイト出力 | CPU readback 用の、1画素あたり4バイトです。 |
順序はマテリアル設定、PrepareDecode(source, material)、必要なら準備 Blit、バイト Blit です。準備とバイトパスで、入力、サンプルサイズ、ブロック座標、上下方向を一致させます。Luma4 の C# フックと所有権、TSMPCodec API も参照してください。
1. キャリブレーション計算を共有する
Luma4 は16個のシンボルそれぞれを、行1の基準ブロック二つから測定します。コーデック専用 include に次の関数を置き、両シェーダーで TSMPDecodeCommon.cginc の後に含めます。
#if defined(TSMP_CALIBRATION_LUT)
Texture2D<float4> _CalibrationLut;
#endif
float CalibrationLuma(int symbol)
{
#if defined(TSMP_CALIBRATION_LUT)
return _CalibrationLut.Load(int3(symbol, 0, 0)).r;
#else
float a = SampleBlockLuma(symbol * 2, 1.0);
float b = SampleBlockLuma(symbol * 2 + 1, 1.0);
return (a + b) * 0.5;
#endif
}
有効経路は整数テクセルの Load を使い、項目間の補間を避けます。無効経路は元のサンプル位置、平均計算、float 精度を維持します。ペイロードのシンボル判定は変更しないでください。精度を落としたキャリブレーションへの置き換えは、バイト結果を維持する最適化ではありません。
2. 全準備テクセルを書き込む
標準の入力/ブロック/サンプル/flip プロパティ、Cull Off、ZWrite Off、ZTest Always、target 3.5、共通 vertex 関数を使う準備シェーダーを作成します。TSMPDecodeCommon.cginc と上の関数を含め、次の fragment 関数を使います。
float4 frag(v2f i) : SV_Target
{
int symbol = (int)floor(i.pos.x);
return CalibrationLuma(symbol).xxxx;
}
この例の出力は16×1です。_OutputWidth と _OutputHeight はバイトマテリアルからコピーされた寸法なので、LUT の項目計算には使わないでください。このコードは実際のラスタ位置を使います。
準備シェーダーでは LUT キーワード variant をコンパイルせず、TSMPDecodeByteOutput.cginc も含めません。常に元の画像から測定して float 値を書き込みます。特に、出力中の _CalibrationLut を読んではいけません。このパスでは blending、sRGB 変換、mipmap、Half 変換、RGBA8 バイトパッキングを使わないでください。
3. 両方のバイトデコード variant を維持する
バイトシェーダーの Properties に [HideInInspector] _CalibrationLut ("Calibration LUT", 2D) = "black" {} を宣言し、プログラムに次を追加します。
#pragma multi_compile_local _ TSMP_CALIBRATION_LUT
同じキャリブレーション関数を含め、既存の DecodeByte(int byteIndex) を維持し、その後に TSMPDecodeByteOutput.cginc を含めます。基底フックは各パスの開始時にキーワードを解除し、LUT を準備できた場合だけ再度有効にします。保存されたマテリアルで無効だった variant がビルドから消えないよう、multi_compile_local を使います。
準備マテリアルとバイトマテリアルは別にしてください。ヘルパーはプロパティをコピーしますが、準備シェーダーを置き換えません。プレハブに両マテリアルを設定し、パッケージ内のシェーダー参照を維持します。
4. 二つのパスをまとめて検証する
最後のバイトシェーダーだけでなく、準備とバイトパスの合計を元の経路と比較します。小さい payload では追加 Blit の費用が上回ることがあります。Luma4 は有効サンプルサイズ1で元の経路、それより大きい場合に準備経路を使います。
正常色と変化させた色、両 Y 方向、自動/明示サンプルサイズ、RGBA の一部だけを使う出力、入力変更、準備マテリアル不足でバイト一致を確認します。パッケージのプレハブ、無効化と再有効化、複数コントローラーも検証してください。Player を実際にビルド・実行し、両 local variant が残ることを確認します。Editor のみでは不十分です。
LUT の割り当ては再利用しますが、有効な各パスで内容を更新します。TSMPDecoder は固定した入力スナップショットを準備・バイトシェーダーの両方に渡します。LUT 準備は元画像を再キャプチャせず、前のデコード処理の値も再利用しません。コーデックを直接呼ぶ実装では入力画像を自分で固定してください。
シェーダ インクルード パス
パッケージ シェーダーは、パッケージ安定したインクルード パスを使用する必要があります。シーン フォルダーに依存する相対インクルード パスは、パッケージがプロジェクトとパッケージの場所の間で移動される場合に脆弱になります。
パッケージが VPM パッケージとしてインストールされた場合でも機能するインクルードを優先します。
精度ルール
- ヘッダーのサンプリングを正確に保ちます。
- ペイロード シンボルでのフィルタリングを避けます。
- バイトリカバリにはポイントサンプリングを使用します。
- 現在のペイロードで使用されているすべての出力ピクセルをクリアまたは上書きします。
- 表示される古いブロックを避けるために、可能な場合は未使用の出力ピクセルを確定的なままにしておきます。
材料特性
カスタム コーデックは、シェーダー プロパティを文書化する必要があります。一般的なプロパティは次のとおりです。
| 財産 | 意味 |
|---|---|
_MainTex | ソース フレームまたはペイロード テクスチャ。 |
_PayloadByteTexture | 中間バイトのテクスチャ。 |
_PayloadSize | 有効なペイロードのバイト数。 |
_BlockSize | コーデックのブロック サイズ。 |
_SampleSize | デコードサンプルサイズ。 |
_CodecOptionBytes | コーデック固有のオプション ベクトル。 |
安定したプロパティ名を使用して、エディターのセットアップとランタイム コードが特殊な場合を除いて値を割り当てられるようにします。
検証
コーデック シェーダーを出荷する前に:
- 確定的なバイト シーケンスをエンコードおよびデコードします。
- フルではないペイロード サイズをテストします。
- コーデックを切り替えて、古いブロックが残っていないことを確認します。
- キャプチャ スケーリングを無効にしてテストします。
- ユーザーが出荷するのと同じレンダー テクスチャ サイズでテストします。