After Effects エフェクトプラグインをゼロから作って見よう 8回目 "NoiseHorizeon"
今回はオリジナルとして新規のエフェクトです。
水平方向に特化したノイズエフェクトです。TVやムービーは水平スキャンラインでデータ収納されているのでデータの欠損等あると水平方向に画像乱れ(ノイズ)が発生しやすいので作った物です。
まぁ簡単な画像処理のサンプルとしていいかなと。
ダウンロード
いつも通りgithub(https://github.com/bryful/NF_Plugins)で公開しています。
Windows用のバイナリは(NF-NoiseHorizon.aex)ここからDLできます。
パラメータ
このプラグインは複数のエフェクトを内部に複数あり、その組み合わせで処理しています。
movingパラメータ
onで全フレームで描画を行います。offではパラメータの変化のあった時だけです。
PF_Cmd_QUERY_DYNAMIC_FLAGSセレクタ時にout_dataP->out_flags のフラグビット値をPF_OutFlag_NON_PARAM_VARYでビット演算させて実装しています。
glovalValueパラメータ
以下のパラメータすべてに影響するパラメータです。単純にノイズの強弱を制御する為のものです。
RGBShift
RGBチャンネルを個別に左右にぶらすエフェクトです。
rgbs_seed 乱数の初期値。movingがoffの時にこれを変化させる事でエフェクト個別にアニメーションさせることが出来ます。以下のエクスプレッションを適応させるとコマ落ちした動きにすることが出来ます(普通にキーを打ってもいい)
koma = 3;
Math.floor((time/thisCom.frameDuration)/koma)*koma;
shiftValue
この後のRedShift/GreenShift/blueShiftの共通のパラメータでパーセントで量を制御します。
RedShift/GreenShift/blueShift
RGB各チャンネルする移動幅の最大値です。
RandomShift
指定されたサイズの矩形をランダムに左右にコピペします。
rsValue
コピペする回数です。
rsSize
コピペする矩形の縦横サイズの最大値です。
xShift
コピペするx座標の最大値です。
Scanline
RandomShiftが矩形ですが、こいつは水平ラインすべてを左右に移動させます。
slValue
水辺ライン毎にずらすかずらさないかを判定する確率値です。
0で全くしない、100で全ラインずらします。
slShift
ずらすx座標の最大値です。
SwapLine
スキャンラインをswapHeightの高さで指定された矩形を適当なY座標にコピペします。
swapvalue
コピペする回数。
swapHeight
この高さの矩形としてコピペします。最大値です。
noise
良くある1ピクセルのノイズですが、横幅が指定できます。後適当な矩形で塗りつぶしも行います(ノイズが増えていくと画面が淡泊になるのを防ぐ為)
上のムービーノイズが止まって見えますね。ビットレート低過ぎでした。
noiseValue
ノイズ量です。
noiseLength
ノイズの横幅です。
noiseStrong
ノイズの濃度(%)です。
drawLine
単純に横線を適当なグレーの色で描画します。
適当なY座標を決め、その上下適当なy座標位置にrsValue2個の線を引きます。それをrbValue回繰り返します。
水平ノイズ
上記のエフェクトを組み合わせてなんとなくかっこいいノイズを作ります。
今回は移動系のエフェクトばかりで輝度変化等のエフェクトは入れていません。後、モザイク系も。まぁ機会があったら作ります。
モニタのノイズ処理というと貞子の奴が有名ですね。VHS系のアナログ特有のノイズがいい味出してます。
昔はモニタのノイズと言ったら貞子とあとアナログテレビ終了後のホワイトノイズが基本でした。放送終了後は生の空電ノイズが表示されてて結構ドラッグムーピーっぽくって好きでした。
しかし、時代変わってデジタル時代ではほぼ画面ノイズはなくなりました。デジタルの特徴でTV放送ではノイズをほとんど見ることがなくなり、変わってよく見るのがYoutubeでの再生ノイズで、これノイズというか遅延等の影響で圧縮された映像を展開時にミスった為画面が崩れる物です。
まぁ今回のエフェクトはそれに対応するために考えた物です。
最初は、画像を適当な圧縮(jpegか横ランレングス)で圧縮して実際にそのデータにノイズを混入させた後展開した物を表示するを考えていました。
が、実際に作ってみると制御が難しい。簡単な圧縮ではちょっとデータが壊れるともう画像にならないただの真っ黒になってしまう。諦めました。
圧縮を配信に特化した奴にすればいいのですが、そういう奴有料で使えなくて。
プログラム的な話
画像処理の解説しようと思ったけどソース見た方がわかりやすかったので略。
今回は内部バッファーの話。
今回みたいに画面のコピペをするときに内部で別に画像を持つ必要があります。
F's pluginsではhandleで直接メモリを確保してそれを内部バッファーにしてましたが、今回から PF_EffectWorldを作成してそれをバッファーにしています。
SDKの画像処理のAPIがそのまま使える。NFWorldも使えるので扱いがらく。handleでのメモリ確保は小さなメモリを確保するときは楽ですが、大きいときはエラーが出やすく1画面分のメモリを確保が出来なかったりします。
PF_EffectWorldだと当たり前ですがメモリ関係が安定します。
昔は作成にかなり時間かかって嫌だったのですが、今はほとんど瞬時で機にならなくなってます。
ただ欠点として小さいサイズの確保するとエラー起こすのでスキャンライン1列分の画像が作れなくて高さ8px以上はないと駄目な事くらいです。
F'sの奴を移植するときはhandleからPF_EffectWorldに変えるつもりです。
たまに起きてる再現性があまりないハングの原因じゃないかと判断しています。
最後に
今F's Spatteringエフェクトの移植しています。
目標はテクスチャーを内部データだけでなく別のレイヤから獲得できること、メモリ関係の安定性です。
まぁ今回のエフェクトはそれの実験って意味がかなりあります。