2010-06-04

アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成

スパッタリングとは

この業界に入って知ったテクニックで驚いたのが、「画面動」・「サブリナ」・「スパッタリング」

新人時代、動画の出来があまり良くない爆発のカットを、演出さんが「画面動」・「サブリナ」・「スパッタリング」を追加することでびっくりするほど見栄えのいいものに変えていたのに凄い衝撃を受けたことがあります。最近ではいろいろな事情があってサブリナが使われなくなり、デジタルになってからスパッタリングもほとんど見られなくなりました。

と、言う事で今回のネタは「スパッタリング」
知らない人の為に説明すると、細かい網に絵の具を乗せてブラシでこすって細かな粒をセルに吹き付けるテクニックのことで、昔は爆発とかには必ず入ってたものです(水面の波とか、雨しぶきとかにも)

プラグインの仕様を考える

アルゴリズムとしてはかなり簡単なもので以下のようになります。
  1. 描画位置を決める。
  2. 決めた描画位置付近に適当な数の粒を描画する。
  3. 以上の描画を適当な回数繰り返す。
というように簡単ですが、それゆえにパラメータ化するのは結構面倒です。
今回のプラグインは、描画位置を決める方法を3種類としてプラグインを分けて作成します。
実際に業務で使う時に楽になるように以下の方法で描画位置を決めます。
  • 範囲で指定。
    TopLeft/BottomRightの2点の位置パラメータから
  • 範囲の中心で指定。
    中心位置・半径等のパラメータから
  • 画像のアルファー情報から
    画像のアルファーの値から描画する位置を決める。
その描画位置から複数の粒を描画する方法は、予め粒子のデータを作成しておいて単純にコピーするにします。粒子の描画のアルゴリズムを考えるより現実的な手段をとります。

sputteringRect

まずは、矩形範囲にスパッタリングするプラグイン「sputteringRect」について説明します。

まずは、ソースのダウンロード。
sputteringRect_src.zipのダウンロード


パラメータは以下のようにしてあります。
パラメータ名 説明
seed A_long 乱数の初期化の数値。
value A_long 粒子の発生起点の数
opacity_rand PF_Fixed 粒子の不透明度の最大値
TopLeft PF_Point 発生範囲の左上の座標
BottomRight PF_Point 発生範囲の右下の座標
point_value A_long 一つの発生起点から描画される粒子の数
point_length A_long 一つの発生起点から描画される粒子の位置の最大距離
size A_long 粒子の大きさ(小のみ・中のみ・大のみ・小+中・小+中+大の5種類あり)
color1 – 4 PF_Pixel 粒子の色(最大4色)
color_Max A_long 粒子の色の最大数の指定
Blend with original PF_Booleanl 元画像を表示するかしないか



描画のメインコードは以下の通り。いろいろ見慣れない変数・関数名がありますが、後で説明します。

メイン(MainRender8)から描画用のコードは分離して関数化してあります。その際にパラメータの記述を簡潔にするためにパラメータはすべて構造体として、ポインター渡しにしてあります。

sputDrawPrmは、粒子描画関数(SputDataDraw)のパラメータ用の構造体。

rotPrmは、角度計算関数(rotCalc)のパラメータ用の構造体。


特に難しいコードではありませんが、補足説明します。

194行目の無駄っぽいループは、案の定rand関数が変な結果を出したので追加したものです。

203行目は回転の乱数を求めている部分ですが、固定小数の桁あふれ防止のためちょっと変な感じになってます。

205行目の処理は、あまりにも丸く綺麗に粒子が並んでしまったので、乱雑さを出すために5分の1の確率で距離を2倍にしています。本当はパラメータ化した方が良さそうな部分です。

SputDataDraw8 粒子の描画

粒子の描画は、SputDataDraw関数が行っています。

spudDrawPrm構造体のメンバは以下のとおりで、描画に必要な最低限のパラメータをまとめてあります。
メンバ名 説明
data PF_PixelPtr 描画画面の先頭アドレス
width A_long 描画画面の横幅ピクセル
widthTrue A_long 描画画面の実際の横幅ピクセル
height A_long 描画画面の縦幅ピクセル
A_long 粒子を描画するX座標(整数値)
y A_long 粒子を描画するY座標(整数値)
opa PF_Fixed 描画する粒子の不透明度
sptIdx A_long 描画する粒子のデータ配列のインデックス
描画する色は、8bit/16bitで分けたかったので、構造体に入れていません。

sptIdxは粒子のパターンデータ配列のインデックスで、今回50個のデータを用意してあります。
50以上の値は、1ピクセルの点として扱うことにしています。135行目からのコードがそれに相当します。

opaは、不透明度は桁あふれ防止のため、呼び出す前に4ビットシフトしてあるので、ここでは12ビットシフトになっています(8bitサイズなので本当は必要ないけど、念のため)

SPT_SIZESPT_VALUEは、粒子のパターンデータ配列にアクセスするためのマクロです、sputteringData.hで定義してあります。

後は、単純に二重ループでデータの転送を行っています。
今回合成先・合成元のピクセルデータのアルファー値は最大値でないので、ピクセル同士のブレンド合成を行っています。

ピクセルの合成(通常) blendPixel

ピクセルの合成は、アルファーの値がどちらかが最大値ならば計算は楽ですが、お互いが透明な場合は少し考える必要があります。僕は全然検討もつかずハマってましたが、googleで検索してやっと見つけました。

悟茶辞苑ッの2007-10-27 土曜日「RGBAのアルファブレンドに感激 -続・レイヤー処理- 」の記事

このHPにそのものズバリがあり、そのままコーディングしたものが以下のものです。

除算が3回も入っていてまだ最適化の余地はありそうですが、特に問題なく使ってます。

粒子データを用意する

粒子データは本当は、実際にスパッタリングした物をスキャンして使おうと思っていましたが、近所の文房具屋にはスパッタリングの道具が打っていなかったので、Photoshopで手書きしました。(僕が小学校の頃は図工の時間でやっていて文房具屋でも売ってましたが最近はやらないみたいです)

データが用意できたらそれをCで扱える形式に変換します。今回は、C#で簡単なツールを作成したので、それで変換します。


粒子データはギリギリのサイズに切り出しておいてください。その時縦横のサイズは同じにしておきます。
Exportすれば、以下のファイルが出力されます。


面倒だったので、マクロ定義なども出力しています。

実行ファイルpic2c.exe
pic2c.zipのダウンロード
ソース(C# 2008 express editionで作成)
pic2c_src.zipのダウンロード

テーブル参照

ここで僕が多用しているテーブル参照のテクニックについて説明します。

テーブル参照のメリットは
  1. 計算を予め終わらせておくので、高速化が望める。
  2. ソースを簡略化して簡単にコーディングできるようになる。
とあります。
しかし、最近のPCでは除算とか小数の計算とかびっくりするほど早くて高速化のメリットはかなり無くなりました。逆にCPUのキャッシュの恩恵を受けられないので、かえって遅くなる場合も多々あります。
そのため僕は主にコーディングを楽にするために使ってます。デメリットは、実行バイナリのファイルサイズが増えるとかテーブルサイズが意外とバカに出来ないサイズになってしまいメモリが勿体無いとか、そもそもテーブル作るのが面倒とかあります。

具体的に説明するためにAfter Effects用のjavaScriptを作成してみます。

AfterEfefctsとじゃんけんゲーム
jyan_jsx.zipのダウンロード
アーカイブに二つスクリプトがはいってますが、動作は同じものになります。
グー・チョキ・パーの3個のボタンがあるダイアログが表示されるので、適当に選ぶとジャンケンの結果が表示されます。

その1のジャンケン判定のコードは、以下の通り。

function jyanStr(v)
{
	var ss = "";
	switch (v){
		case 0: ss = "グー";break;
		case 1: ss = "チョキ";break;
		case 2: ss = "パー";break;
	}
	return ss;
}
var dlg = new jyankenDialog("AfteEffectsとじゃんけんゲーム その1");
var player = dlg.execute();// 0:グー 1:チョキ 2:パー
if ( (player>=0)&&(player<3) ) {
	var computer = Math.floor(Math.random() * 12) % 3; //0-2の整数を返す
 
	var kekka = -1; // 0:引き分け 1:palyer勝利 2:player負け
	switch (player) {
		case 0: // グー
			switch (computer){
				case 0: kekka = 0; break;
				case 1: kekka = 1; break;
				case 2: kekka = 2; break;
			}
			break;
		case 1: // チョキ
			switch (computer){
				case 0: kekka = 2; break;
				case 1: kekka = 0; break;
				case 2: kekka = 1; break;
			}
			break;
		case 2: // パー
			switch (computer){
				case 0: kekka = 1; break;
				case 1: kekka = 2; break;
				case 2: kekka = 0; break;
			}
			break;
	}
 
	var s = "じゃんけん勝負\n\n";
	s +=";Palyer : " +jyanStr(player)+"\n";
	s +=";AfterEfefcts : " +jyanStr(computer)+"\n\n";
	switch(kekka){
		case 0: s += "引き分け\n";break;
		case 1: s += "あなたの勝ち\n";break;
		case 2: s += "あなたの負け\n”;break;
	}
	alert(s);
}


見やすいようにswitch文で処理してますが、if分で書いても多少短くなる程度です。
その2はテーブル参照でジャンケン判定を実装したもので以下のようになります。

var dlg = new jyankenDialog("AfteEffectsとじゃんけんゲーム その2");
 
var player = dlg.execute();// 0:グー 1:チョキ 2:パー
if ( (player>=0)&&(player<3)) {
	var computer = Math.floor(Math.random() * 12) % 3; //0-2の整数を返す
 
	var kekkaTbl = new Array(0,1,2,2,0,1,1,2,0);
	var kekkaStrTbl = new Array("引き分け","あなたの勝ち","あなたの負け");
	var jyanTbl = new Array("グー","チョキ","パー");
 
	var s = "じゃんけん勝負\n\n";
	s += "Palyer : " + jyanTbl[player]+"\n";
	s += "AfterEfefcts : "  + jyanTbl[computer]+"\n\n";
	s += kekkaStrTbl[kekkaTbl[player * 3 + computer]]+"\n";
	alert(s);
}


なんと、半分以下になっています。テーブルを作成するのが面倒ですが便利な関数を呼び出す気分で使えます。
このスクリプトではテーブル参照を2重で行ってますが、それをひとつにまとめればさらに短いコードに変えられます。

余談ですが、AfterEfefctsは意外とジャンケンが強いです。作成時10回連続で負けたので、バグがあるのかとハマってましたが、単純に運の問題でした。

粒子をランダムに選び出す。

描画する粒子を選ぶ方法は、要素数200のジャンプテーブル(sputteringCircle_ParamssputRandTable)に51種類のインデックス番号を適当に配置してランダムに選び出すことで実装しています。
sizeパラメータは、ジャンプテーブルへの配置の仕方を変えているだけで、描画関数内ではただランダムに選ぶだけです。

sputteringRect.cppSetupSputData関数でジャンプテーブルの初期化を行っています。


for文の嵐になってますが、sizeのパラメータに合わせて適当な数値を入力しているだけです。

同様に粒子の色も配列で確保しておいて、ランダムに選び出してます。

乱数

スパッタリングでは粒子の描画のばらつき具合が重要なので、乱数発生に注意しています。
今回FR_RAND(LO,HI)FM_RANDの二つのマクロを定義しています。

#define FR_RAND(LO,HI) (A_long)( F_RAND() * (HI – LO + 1.0) / (1.0 + F_RAND_MAX))
#define FM_RAND(HI) (A_long)( F_RAND() * (HI + 1.0) / (1.0 + F_RAND_MAX))

この公式は乱数発生の基本的なもので、FR_RANDは範囲乱数を求めるもの、FM_RANDは最大数値を指定するものです。
精度を上げる為実数計算を含んでいるのですこし実行速度が遅くなりますが、まあ無視していいレベルです。実はまだ精度的に納得できないモノですが、速度との折り合いで僕は我慢して使っています。

乱数発生は画像処理ではかなり根底問題で毎回苦労します。

F’s ScreenShakeDir.aexでは自前で乱数テーブルを用意しています。画面動では精度の良い乱数であっても見た目のばらつきと一致しないので、テーブルの数値は計算で求めないで実際の画面動を見ながら手で入力しました。実際に見てもらえばわかりますが、範囲も100までで(8Bit長も使っていない)乱数テーブルとしてはかなりいい加減なものですが、結果的に一番満足しています。

有名なMersenne Twisterの乱数発生アルゴリズムも試した事がありますが、かなり精度の良い乱数は得られますが、それが画面には反映されずかえってばらつきが均一になり見た目の乱雑さが失われしまいました。結局速度のことを考えて標準関数で乱雑さをアルゴリズムで補ってます。

乱数とアニメ撮影技術の関わりを考えていくと、人間工学やらエントロピーとか難しい所に到達してもう僕のスキルでは手に負えません。最近ではすぐに諦めて簡単な方法に走ってしまいます。

今回のsputteringRectでは、粒子の大きさの発生ではジャンプテーブルで発生分布をばらつかせていたり、粒子の発生距離は、適当な確率でパラメータ自身を変化させて見た目のバラつきを発生させています。

sputteringCircle

sputteringCircleはスパッタリングの描画範囲を、その中心位置・半径パラメータで決めているもので描画事態はsputteringRectと同じものです。

パラメータは以下の通りです。
パラメータ名 説明
seed A_long 乱数の初期化の数値。
value A_long 粒子の発生起点の数
opacity_rand PF_Fixed 粒子の不透明度の最大値
Pos PF_Point 発生範囲の中心位置
Radius A_long 発生範囲の半径の最大値
Aspect PF_Fixed 発生範囲の縦横比
length_scale PF_Fixed 発生点と中心との距離のスケール率
Anchor_enabled PF_boolean スケールの中心を有効にする
Anchor PF_Point スケールの中心
point_value A_long 一つの発生起点から描画される粒子の数
point_length A_long 一つの発生起点から描画される粒子の位置の最大距離
size A_long 粒子の大きさ(小のみ・中のみ・大のみ・小+中・小+中+大の5種類あり)
color1 – 4 PF_Pixel 粒子の色(最大4色)
color_Max A_long 粒子の色の最大数の指定
Blend with original PF_Booleanl 元画像を表示するかしないか

length_scaleとAnchorのパラメータは爆発なんかに適応させる場合にこのパラメータだけで指定できれば楽そうだなって意図で採用してあります。

アルゴリズムは以下のようになります。
  1. Posの位置からRadius(半径の距離)Aspect(縦横比)とlength_scale/Anchorを考慮して描画点決める。
  2. 描画点から最大point_lengthの位置にpoint_value分の粒子を描画。
  3. 上の描画をvalue回繰り返す。
第3回目の記事で作成したFireworkプラグインとほぼ同じアルゴリズムになっています。
以下はMainRender関数の重要な部分を抜き出したものです。

sputteringAlpha

sputteringAlphaはスパッタリングの描画範囲を、画像のAlpha値で求めるもので描画事態はsputteringRectと同じものです。
Alphaが決められた閾値以上のピクセルを対象に適当な確率で描画点を発生させています。そのままだと細い線とか面積の少ない部分にあまり描画が行われなくなってしまうので、境界部分は個別に発生の確率を変えられるようにしてあります。

パラメータは以下の通りです。
パラメータ名 説明
seed A_long 乱数の初期化の数値。
value(%) PF_Fixed 不透明部分の粒子の発生確率
edge_value(%) PF_Fixed 境界部分の粒子の発生確率
opacity_rand PF_Fixed 粒子の不透明度の最大値
point_value A_long 一つの発生起点から描画される粒子の数
point_length A_long 一つの発生起点から描画される粒子の位置の最大距離
size A_long 粒子の大きさ(小のみ・中のみ・大のみ・小+中・小+中+大の5種類あり)
color1 – 4 PF_Pixel 粒子の色(最大4色)
color_Max A_long 粒子の色の最大数の指定
Blend with original PF_Booleanl 元画像を表示するかしないか


このプラグインでは、境界線を識別して保存するために1画面分の配列を作成しています。少しでもメモリを節約するためにA_u_charの配列にしています。
sputteringAlpha.cppRenderで配列用のメモリを確保しています。


境界線の識別はsputteringAlphaMain8.cppMainRender8関数で行っています。高速化のの為に上下左右1ピクセルは無視して識別を行い、境界線・不透明部分と数値を分けて退避用の外列に値を書きこみます。アドレス計算はオフセット値を予め計算してジャンプテーブルを作成して行っています。


描画はNoise04Lvと同じようなコーディングになっています。

このサンプルプラグインについて (F’s Pluginsへ)

この3個のプラグインはパラメータの扱いが違うだけで描画ルーチンは同じものです。何故分けたかというと、実際にスパッタリングを行う場面を考えて使いやすいように考えたからです。
プログラム的には一つにすることは可能ですが、エフェクトコントロールがこれ以上増えて見づらくなるのが嫌いという理由もあります。

あと、このプラグインはサンプル用に作ったもので、よく見ればFirework/Noise04Lvを少し修正しただけに過ぎません。でも、意外と業務に使えそうな雰囲気になってきたのでsputRandTableをもっとましにするとか、16bit化するとかしてからF’s Pluginsとして公開配布するつもりです。

2010/06/05追記
早速作りました。
Windows版 F’s sputtering
FsSputtering.zipのダウンロード
Macintosh版 F’s sputtering(beta)
FsSputtering-Mac.dmgのダウンロード

AEP projectサンプル版から以下の項目を修正してあります。
  • 16Bit対応
  • 粒子のテクスチャを修正。
    50個から60個へ増やした。サイズを修正。
  • sizeのパラメータを修正。
  • suputteringSplashを追加。
  • MT版とMacintosh版を作成
ソース・プロジェクトはWindows版のアーカイブ内に入っています。

次回予告

次回は予定通り「Effectsプラグインの構造」です。

この記事は全部で全10回と予定してましたが、少し短くなって全8回程度になります。



タグ : , [タグを追加する]


この記事の投稿者について:bryful

フィードバック

1 Star2 Stars3 Stars4 Stars5 Stars
(評価回数:3 , 平均:3.67)
Loading...Loading...

この記事に対する 20 の反応があります


  1. 1 かれん 6月 3rd, 2010 at 16:55

    Now browsing:アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 | AEP Project http://bit.ly/b84a5f

  2. 2 アーマードあみすけ 6月 4th, 2010 at 08:59

    アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 http://j.mp/9nIKd7

  3. 3 tetu 6月 4th, 2010 at 18:04

    初めまして。最近AE pluginを作り始めて色々調べてこちらのサイトにたどり着きました。
    わかりやすく丁寧な解説で非常に助かります。

    私は画像に手を加えるのではなく画像(レイヤーなど)情報を取得しファイルに出力する
    プラグインを作りたいと思っています。
    色々調べてはいるのですが、プラグイン側からテキストファイルを作成し情報を書き込む事は
    可能でしょうか?
    いきなりで申し訳ありませんが、時間の空いている時にでも返信下されば幸いです。
    環境はWIN,AE7です。

  4. 4 bry-ful 6月 4th, 2010 at 21:51
    bry-ful

    >色々調べてはいるのですが、プラグイン側からテキストファイルを作成し情報を書き込む事は
    >可能でしょうか?

    可能です。
    SDKのAEGPプラグインのProjectDumperがまさにそのサンプルです。実行するとプロジェクトに登録されたフッテージ・コンポジション・レイヤの情報をテキストファイルに書き出すプラグインになります。

    SDKのドキュメントのAEGPの項目に詳細が説明されています。

    まぁ単純にプロパティ等を出力したいのなら、スクリプトでやった方が楽ですが。
    http://bry-ful.ddo.jp/BRY/softwaew/getLayerInfo.zipがレイヤのプロパティを書き出すスクリプトです。

  5. 5 tetu 6月 7th, 2010 at 10:13

    お礼が遅くなりました。

    的確なアドバイス有り難うございます。
    スクリプトはある程度出来ていたのですが、プラグインの勉強も兼ねて作成して見たかったので質問しました。
    ProjectDumperのソースを見ながら色々テストしてみます。
    本当に有り難うございます。

  6. 6 llcheesell / t.ogata 6月 8th, 2010 at 07:36

    みてる RT @AEUSERS: アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 http://bit.ly/aXIHIS

  7. 7 ネオライス 6月 8th, 2010 at 07:39

    RT @llcheesell: みてる RT @AEUSERS: アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 http://bit.ly/aXIHIS

  8. 8 遊太郎 6月 8th, 2010 at 07:56

    RT @AEUSERS アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 http://bit.ly/9ky4A2 #aejp

  9. 9 くるみ(ピュア) 6月 8th, 2010 at 07:57

    RT @youtalow: RT @AEUSERS アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 http://bit.ly/9ky4A2 #aejp

  10. 10 uzura 6月 8th, 2010 at 08:19

    アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 | AEP Project: 描画する色は、8bit/16bitで分けたかったので、構造体に入れていません。 sptIdx… http://bit.ly/dAv8dq

  11. 11 xxkjuxx 6月 8th, 2010 at 14:13

    RT @uzura9: アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 | AEP Project: 描画する色は、8bit/16bitで分けたかったので、構造体sptIdx… http://bit.ly/dAv8dq

  12. 12 AEUSERS(AEP Project) 6月 12th, 2010 at 16:20

    新着記事 : アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 http://bit.ly/bFlzhJ

  13. 13 highluin 6月 12th, 2010 at 16:26

    RT @AEUSERS: 新着記事 : アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 http://bit.ly/bFlzhJ

  14. 14 zdmrmtqynzo 3月 7th, 2011 at 11:40

    EBRKOv tyntkpkzrtgs, [url=http://vxhoinmfrnkr.com/]vxhoinmfrnkr[/url], [link=http://lutctnujeotq.com/]lutctnujeotq[/link], http://wkhkicquhwjj.com/

  15. 15 ラグス@シルナ 1月 8th, 2012 at 17:02

    @inukotyan 多分、すでに検索済みだと思うけど・・・

    http://t.co/ozvvmaVE 
    http://t.co/CEPJ02pM 
    http://t.co/GHfxZiUQ 

    自分はやった事ないから、参考になるか判んなくてすいません(´・ω・`)

  16. 16 ゼフィール 7月 27th, 2012 at 12:21

    初めまして。ゼフィールと申します。
    最近、AfterEffectsのPluginを作り始めました。
    こちらのサイトはわかりやすく丁寧な解説で非常に助かっております。

    私はコンポジションから指定した場所の色を取得したいのですが、そういったことは可能でしょうか?
    恥ずかしながら、個人的に色々と調べたのですが、答えが見つからず・・・。

    私の環境は Windows / AfterEffects CS4 を使っております。

    突然の質問で申し訳御座いませんが、お時間の空いている時にでも返信を下されば幸いです。
    お手数で御座いますが、宜しくお願い致します。

  17. 17 mostalzmqp 10月 13th, 2012 at 05:57

    使えそう・・・ http://t.co/0J04DCh4

  18. 18 memoblog 10月 17th, 2012 at 04:38

    アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回) スパッタリングプラグインを作成 http://t.co/KfaO9jC5 スパッタリングっていうのか

  1. 1 アニメ制作者のためのAfterEffectsプラグイン作成入門(第5回)スパッタリングプラグインを作成 | Tips - After Effects - 動画編集ソフト - アプリケーション | Jishuu.net Pingback on 4月 21st, 2012 at 05:29
  2. 2 アニメ制作者のためのAfter Effectsプラグイン作成入門(第5回)スパッタリングプラグインを作成 | チュートリアル・Tips - After Effects - 動画編集ソフト - アプリケーション | Jishuu.net Pingback on 10月 3rd, 2012 at 20:39

特集