ドリクラエミュ弄り:二画面化改良等

 えー、正直に書きますが今回は前置き=書き出しに非常に悩まされました。というか、います。
 最近は色々と良くないニュースばかり耳にしてしまうところで。誰も彼もかは分かりませんが気が滅入っているこの頃ではないかとは思います。

 ここで何ぶん、自分が近頃やっていることは割とアレだという自覚を持ちつつやっている物なので参考、流石にちょっといつまでもふざけても居られない気分にもなってしまうところ。

 この辺実際、普段ならこういう事は書くべきことではないという自責もあるので、せめてもう少し本音を織り交ぜつつもよく分からない茶化しを入れて中和を図るくらいの事はするところなんですが。ちょっと今回はあまりにも上手く行かなすぎて諦めた感。

 まぁ最初に言い訳さえ織り込めれば、後はいつも通りの通常運転にもなろうかとは思いますが、、。

 という訳でドリクラ小話というか、近況と申しましょうか。
 しばらくは呑気に動画を録る気分にもなれない所だったので、そのぶんコード作業の方を進めていた訳ですが、これがまた困った事にあれもどれもなかなか上手い結果を出せず。まさかの「全滅ぅ?」みたいな危機的状況にも追い込まれつつ。いや実際には全滅でも何でもない(上手く行っている小ネタもある)のだけれど、ただ立て続けに詰まってしまうと気分的な落とし所も作れないままになってしまうという。

 まぁ半ばヤケクソに食らいついていたらようやく一つ突破口が見出せたという所で、ここらで近況報告も兼ねまして。
 今回は与太話オンリーですのであしからず、、。

●データ移植
 前回はまだ特定データ相手のデモバージョン状態だった所からもう少し整理も進めまして、一応全バージョンの衣装データについては一通り変換コードを走らせられるようになったという所まで。ここから「互換性の取れない部分」の調整に入らないといけないというところ。まだ「先は長い」という感じですね安駄婆。まぁ物によっては現状でも使える物もなくはないのですけども。

 具体的に言うと最も厄介なのが「揺れ制御データ」周り。思った以上に大分変わっているみたいですね。ええ、思った以上に(汗)。前回のノコ衣装ではここは完全に手作業の調整データをぶっ込んだので、そんなことを全衣装にやっていられる訳もなく。果たしてどう汎用的に互換の取れそうな落とし所を見付けていくか。
 しかしこれははっきり言ってしまうと手酷い逆コンバート作業なので、開発関係者の方々から言わせれば「やめろ」としか言われないレベル。不毛ゾーンに両足両手どころか頭まで突っ込んでる始末(苦笑)。

 まぁ一度キリは良くなっているところで一旦手を置いてます。
 如何せん何とも「しんどい」作業ではありまして。

 あ、あと一つだけ訂正報告。前回のノコ衣装はスカートの裏地がなくなってました、ごめんね(てへぺろ)。何度も調整を重ねてほぼ悔いの無い作りに仕上げたつもりだったのに、まさか初歩的な見落としをしていたとは、、。まぁ詳しくはまたいずれ。


●コード環境
 えー、何がしんどいかって、lua(プログラム言語)が割としんどい。
 元々CheatEngineから使える連携用スクリプト言語がlua。一方、上記のデータ変換部分等については静的にプログラム実行を掛けるところなので別にどの言語で書いても構わない訳ですが、ただ今回はノウハウを積む意味でも全部luaで書いてみようかと。
 実際その目論見としてはある程度功を奏してはいるものの、同時に払ってしまっている代償も大きいというか。開発効率的に非常にもどかしい部分が多々。いやはや普段どれだけ言語機能とIDE(開発環境)の恩恵に与っているかというのを思い知らされているこの頃で御座います。

 元々luaは高速性を重視したプリミティブな言語仕様なので、あくまで「こう書けば似たような事は出来る」というノウハウの集合体でしかない。それが昨今のIDEの各種言語サポート機能とは全く結びつかないので自分で泥臭く管理する部分が多い。もう少しどうにかならないものかと調べるはするけれど、まぁ言語仕様的にしょうがないよねとなる部分は多いと思う。
 お陰で不本意な泥コードも多くなってしまい、ぶっちゃけ今からでももっと融通の利く他言語で書き直した方がこの先の改良・メンテも含めてよっぽど早く済むんじゃないかと錯覚してしまいたくなるような。まぁ流石に時間的にはロスするだろうけど、、でもね、という感じで。

 そんな訳で(まぁluaだけの所為じゃないけど)随分と疲弊してしまったので、一旦キリの良さげなところで手を置いて、小休止に他のプログラム解析に移ってしまった次第。先は長いですし。
 いやまぁアセンブラもアセンブラでしんどいですけどね(笑)。ただしんどさの質が違うので。
 あとデータ解析だとガチでデータバイナリとコードとの睨めっこしかしない日々が延々続くので、そういうのも身体に悪いと思います(笑)。


●動画の撮り方・作り方
 昨今、皆さんが上げられる動画は、色々組み合わせにも凝った物が多いですよね。まぁもう発売して10年以上経過しているソフトなので、今更ただの標準ストリーム動画もないよねと言ってしまえばそうで。
 でもね、そもそも皆さんアイリの動画はそんなに上げてくれてないじゃないですか(笑)。
 自分の出発点はあくまでそこなんですよねぇ。元々は、幾つか「こんなことも出来るよね」くらいのネタ振りを織り交ぜつつ、個人保存用にアイリの全制服動画とかを上げてお仕舞いにするくらいのつもりでした。
 ただパフォーマンス問題にぶち当たって計画が一度頓挫してしまった後、それ以外の物事に手を出していく内に色々と調子に乗って今に至る、という感じでしょうか。

 まぁ今も基本的には技術面の掘り下げと悪戯重視で、動画製作そのものにはあまり凝っていない訳ですが。ただ折角上げる(見て貰う)ならもうちょっと見栄えの良くなるようにも考えていかないといかんのだろうなぁとは思いつつ。例えば二カット分組み合わせるだけでも情報量は二倍ですからねぇ。
 そこはただ二回録ってくっつけるだけじゃんと言えばそうなんですが、しかし当然作業量も二倍ですし。何よりエミュの録画の安定性の問題もまだあるので、録って確認してやり直しになるリスクは出来るだけ減らしたいというのが実情でして(苦笑)。


●二画面化改良1
 そこで前から考えてはいたのが、以前に作った二画面化改造の応用。
 例えばこれまで何度か上げてみたような「ストリーム+スイッチャー(固定視点)」の二カット組み合わせ。これも二画面化で二回計算させる際にカメラデータ処理をストリームとスイッチャーで流せば行けるんじゃないのと。

img

 はい、割と何とかなりましたの図。
 画面比率は計算を変えれば行けるのでそこも可変式に再改造。半々以外にも対応可。
 もっとも二画面化は負荷が割とギリギリなところはあるので、重めの衣装では使い辛いんですけどね。まぁ速度を追い求めた水着なら!(笑)

 ただ一つ思い出したのがバックスクリーン問題。(上記図は敢えて失敗版)
 ここを解決出来ないとステージが限定されて微妙になってしまう。


●バックスクリーン
 こちら以前の改造では割と厄介だったので保留になっていた部分。
 仕組みとしては描画画面をテクスチャに転送しているので、二画面化するとその二つ並んだ画像がそのままスクリーンに転写されてしまう。だからその転送座標を変更してやらないといけない。
 実際には画面の中央部分が切り取られているので、その座標指定を変えてやればいいのだろうと処理を探したのだけれども、これがなかなか全く上手く行かず。加工処理されている以上は何処かに数値を持っている筈なのにまるで糸口が掴めず。あれやこれやと周り道しながらようやく辿り着いた先は、どうにも直接DirectXに流し込む描画命令の部分。

 そこから先は都合上追うのが厳しいので、やむなく手口を変えてプランB。
img
 はい、これで何とかちゃんと切り出せるようになりましたよ。

 多少具体的な話でいうと、画面転送の際に一部(画面中央上部)を切り取った上で、更にその切り取った絵に対してモデルのテクスチャUVにてスクリーン投影範囲を更に絞り込むという二段階の構成になっている。この内、前者で転送領域を任意に変更してしまうのが最短なのだけれども、ここがまだよく実態が掴めない所で、(端にずらすなど)ある程度の単位でしか弄れないのが現状。
 そこで前者は全画面を転送させるようにだけして、あとは後者のモデルUV座標を弄って投影箇所を変えるという荒技を決行したのがプランB。このモデルデータの直接書き換えはキャッシュ制御にも絡むので出来る事なら避けたいのだけれど、まぁ取り敢えずこれで任意に動かせるようにはなったというところで。

 尚、一つ制約として(キャプチャには出てないけど)左右画面共に同じスクリーン画像が映ってしまう。
 プランB方式の制約でもあるのだけれど、仮にプランAでもおそらく転送のタイミングの関係上、左右の各描画毎にそれぞれの別の転写を行うというのは厳しいかもしれない、どうだろう(まだ精査は仕切れてないけど)。
 まぁ当面の目的がストリーム+スイッチャーの組み合わせなので、ストリーム側だけ映れば一旦それでいいんじゃないかな。

 というか、負荷的にもギリギリだし結局は制約があるというなら素直に二回録ってしまう方が早いのかもしれませんが。
 まぁでもこう言うじゃないですか、俺は面倒が嫌いなんだって(笑)。
 だから面倒を避けるために手を動かしましょうねと。それを別の面倒と呼ぶのかどうかは人次第(笑)。

 それに座標は任意に変えられるようになった訳で、片方しか映せないのなら逆にもう一方を映すのも面白いというか。以下ちょっとした悪戯心ver。
img
 ええはい、予想通りに酷い絵面になったので程々にしないといけませんが(笑)。冷静に考えると実に酷い羞恥プレイ。ごめんね。

 ともあれこういう形でなら一発取りならではの意味も多少は出てくるのではないでしょうか。


●二画面化改良2
 あともう一つ考えていたのが、デュエットの2キャラ横並び描画。
 高速化改造でデュエットも十分実用的になったので何度か録ってはいたものの(&録る側としてはこれが非常にお手軽)、ただカメラ位置的にどっちつかずになりやすくもあったので、これも各キャラで2回録ってそれを並べるような編集の方が見栄えはいいんだよなぁと。(でも個別画像二回にDuet音声一回で三回録ってるの?という。音声合成で上手くやれるんだろうか(曲だけ被る))

 そこで小賢しくも思い付いたのがこちら。
img
 デュエット改造で1キャラずつストリーム描画。デュアルストリームとでも申しましょうか。
 2回の描画ループ中にそれぞれのキャラ位置にカメラを切り替えて、尚且つ負荷軽減も兼ねて交互に片方のキャラを消して1キャラずつ描画。これで擬似的に2キャラ分のストリーム画像を同時描画。

 うん、割といいところまでは行ってるんですけどね。
 何でかまたセルフシャドウの問題が再発してまして。経験上厄介になりそうなので一旦保留中。

 あとこの場合バックスクリーンは現状一方しか映せないので、上記で言うなら亜麻音ちんの側にもアイリのスクリーンが映し出されるといった微妙な絵面になってしまう。真のデュアルストリームは作れないかもしれない。うーん、どうだろう。

 行けそうかと思ってたんですけどねえ。
 まぁ最悪はステージ限定でならあるいは。


●ちょびっと処理最適化
 これはデータ解析の副産物なんですが、処理を見ていたら少々大分微妙なコードを見付けてしまいまして。
 まぁXbox版初代からの流用コードだと思うので、多分PS移植版ではとっくに改められているだろうし、そんな物を今更あげつらおうというつもりではないのですが。まぁこういう実装の積み重ねは大事ですよねって。

 ストリームカメラの処理を見ていたら、データアクセスの際に少々かなり無駄なループが発生しているのを発見。各フレームのデータを拾う際に毎回データリストの先頭からサーチし直してしまっている。最初はまだ良いけど後半ほど無駄が積み重なっていく。そしてそのサーチが16本くらい行われるので結構な数。
 これでどれくらいの無駄が出るかというと、1フレームに最大12万回くらい(汗)。まぁCPUの世界で言えば10万程度は屁みたいなものですけどね。ただこれで一曲通しで2分強(7-8000フレーム)の間に発生する余計な処理ループの累積数が4億。億ぅ?と思ったけど計算すると確かにそう。それだけ普段CPUは馬車馬以上に文句の一つも言わずに黙々と働き続けてくれている訳ですけどね。CPUに感情がなくて良かったですなぁみたいな(笑)。

 まぁ無印の頃は短時間のカメラデータしか無かったので、軽い気持ちで組んだままそれをZEROの一曲フルのカメラストリームに当てて大変な事になったという感じかなと。目に見えるような処理落ちを起こす訳でもないので、一度見落とすとそれっきりになりやすい類のコードだとは思う。

 ここは普通に考えてデータは順番に入っているものなので、前回読んだ位置を記憶してそこから再開させればいいんじゃないかと試したところで無事改善。累計4億あったアクセスを20万台にまで削減。
 とはいえ1フレームでは最大10万強のロスなのでmsecの影響が出るほどではない、μsecの負荷だとは思いますが。(ms以下は負荷もブレるので比較計測は出来てない)

 ただ段々とサーチが長くなっていく=曲の後半ほど無駄になっていく作りで、前々から「曲の後半の方がフレームドロップしやすい?」傾向を感じてはいたので、まさかなぁと。曲の後半にエフェクトが掛かるケースが多いのでその影響くらいにも思っていたけれど。ただ試してみると確かにギリギリの負荷のケースだと僅かにフレームドロップは改善しているようにも見えるところ。まぁほんの数フレームの話ですけどね。fpsで言えば1改善するかどうかレベル。
 ただね、省ける無駄なら省きましょうよと。気付いてしまったのだからしょうがないですよ(笑)。CPUを労りましょう。

 こういう風に他にも何かなかろうかとは思ったけれど、モーションデータなんかはまた作りも違うので問題無かった。
 まぁ結局一番重いのは描画なので、もっと(分かり易く)削れる処理はないかなぁと(笑)。

 こんな感じで、ひたすらコード技術部門ばかりを進めておりました。
 細かい小ネタも形にはなってきてはいるんですが、あとはデータを整えないといけないので、そこがノリと勢いの必要な部分にはなってしまうところで。

 まぁぼちぼちまとめて行きますかねぇ。折角手を動かしたというのはありますし。