地形破壊が出来るプラグイン「Voxel Plugin」
「新しいプラグインがでてた。動作確認用の実行ファイルもあったから、どんな感じか試してみた」
「FPSテンプレートみたいな感じなんだけど、撃つと地面がえぐれていくという」
妹「なんか面白そう。でもボクセル? ボクセルってそういうのだっけ?」
「立体的なピクセルというか。ポリゴン単位だと、ポリゴンの継ぎ目のとこでしか壊れないけど、内部的にボクセルで計算するからそのへんが自然にできる……ってことだと思う」
「複雑な穴を掘ることもできる。例えばUE4標準のランドスケープだと、各地点の高さを変えて地形を作るから、山は作れても洞窟は作れない。そのへんもボクセルで解決する。ボクセルより小さい単位で地形を加工することは出来ないけど。あまり細かくても動作に影響するだろうし」
妹「遅かったりするのかな?」
「サンプルはデバッグ版ビルドみたいで、昨日の方法でプロファイルを見ることが出来る。特に穴が多くなったからどうこうとかはなかった。破壊中は若干フレームレート落ちるんだけど、これは爆発エフェクトのせいかもしれないからわからない」
妹「ブループリントなの?」
「いやC++みたい。C++のソースコードは付属してるみたいだけど。99.99ドルするけど、こういうのが必要になった時には自作するより手っ取り早そう」
ディフュージョンフィルタを作る(4) 負荷を調べる
「あんまり速度のこと考えずに作ったポストプロセルマテリアルだから、最適化しようかとも思ったんだけど、下手にいじくるとかえって遅くなることがある」
妹「速くなるようにしたのに遅くなるの?」
「最近は内部的なアレコレで高速化してるから、よかれと思ってやったことでその高速化を無効化しちゃうことがある。それに複雑にすると後で読みにくいから、多少速度が上がるぐらいなら放っておいた方がマシな場合も」
www.slideshare.net
「で、丁度UE4のプロファイルに関する資料が出てたから、これを見てちょっとやってみる」
妹「プロファイル?」
「捜査ドラマにでてくるプロファイリングみたいな。誰が遅いのか犯人探しをしようという」
「@キーを押して、入力欄を出して、stat unit と書いてEnterキー」
「昨日のディフュージョン用マテリアルを適用した時としてない時で調べてみた。数字はかかった時間だから、基本的に数字が多いほどよくない。でも誤差の範囲で数字が動くし、違いがよくわからないということがわかった」
妹「計り方が間違ってるのでは?」
「その可能性もあるので、今まで半径6ピクセル(実際には2倍した12ピクセル)の円でボカシてた処理を、半径30ピクセルに改造したものでも試してみた」
「操作していてもフレームレート落ちてるのわかるし、パソコンの発熱量も増えて普段動いてないファンが回りだしたし、明らかな高負荷状態。で、数字もGPUのところが増えてて、高負荷状態であることを裏付けてる」
妹「ということは、計り方はあってた?」
「高負荷にするとなんでDrawの値が逆に増えてるのかとか、気になるとこはあるんだけど。FPSが減って表示回数が少なくなったからそこの負担が軽くなったのかも。何にしても昨日のぐらいの大きさのボカシでは大して遅くなってなかったらしい。体感でも遅くはなってないし。となると最適化とかも別に要らなそう」
妹「もし遅いってなってたらどうしたの?」
「昨日いってたような工夫とか、後はボカシ半径を小さくしたりとか。その場合も数字を見て、効果がある改良かどうかを確かめながらやる必要がある」
ディフュージョンフィルタを作る(3) さらにふんわり加工で
ディフュージョンフィルタ3号機
元の状態
「さらに改良することで、かなりふんわりさせることに成功した」
/* 初期値。ループの中で増やしていく */
float4 total = SceneTextureLookup(uv, 14, true);
float total_alpha = 1;/* ループ開始。表示中のピクセルから縦横に調べる */
/* 範囲が広い方が光を綺麗に広げられるけど、その分重くなる */
for(int y_loop = -6; y_loop <= 6; y_loop++){
for(int x_loop = -6; x_loop <= 6; x_loop++){
/* ピクセルの色を取得 */
/* 2を掛けるのは処理を重くせずボカシの範囲を広げるため。数字が大きいと光る範囲が狭い時に違和感大 */
float4 col = SceneTextureLookup(uv + float2(x_loop, y_loop)*invSize*2, 14, true);/* RGBの数字を元に明るさを算出 */
float light = col.x * 0.3 + col.y * 0.6 + col.z * 0.1;
/* 距離を調べる(ここはもっと高速化できそう) */
float d = distance(float2(0,0),float2(x_loop, y_loop));
/* 距離が遠くなるほど影響力を弱くする */
/* 距離を変換して、中心が1.0で、遠ざかるほど0に近づく数字にする */
float d2 = ((7 - d) / 7);
/* 1は何度かけても1だけど、0.1*0.1だと0.01になる。という理屈で遠ざかるほど数字が急激下がる */
float alpha = light * pow(d2,3);
if ((light > 0.7)&&(d <= 6)){
total += col * alpha;
total_alpha += alpha;
}
}
}/* 足しに足したRGBを最後に割って、色を混ぜ合わせた状態にしたものを返り値にする */
return total / total_alpha;
「これならだいぶ実用的なはず」
妹「ふんわりっていうか、なんかぼんやりしてるね。机の上の……なんか置いてあるやつとか」
「そのへんは原理的にそうなっちゃうと思う。ディフュージョンフィルタに対する理解が間違ってる可能性もあるけど。あと高速化はほとんど考慮してないから、速度の問題は気になる」
妹「例えばどのへんが?」
「ピクセル間の距離をいちいち計算してるのがちょっと。多分二次元配列とかにした方が速い。けどそれをやると中身がわかりにくくなるから」
妹「あ、これはわかりやすい方なんだ」
「めちゃくちゃに最適化した状態よりはたぶん……あとは同じピクセルの明るさを何度も計算してるのも気に入らないけど、これはエンジン改造でもしないと対処がむずかしいのでは」
妹「どのぐらいの明るさからぼかすかっていう基準の問題もありそうな」
「それもパラメータ化して、後から変更できた方が便利そう」