Qullusrent3 独自エンジンについて考察と音楽などについて/Qullusrent3: Thoughts on the Custom Engine and Music, etc.

今回、Qullusrent3をDirectX11にリファインし、Unreal EngineやUnityなどを使わずシェーダ等を全部書いたわけだが、DirectX11は何かと難しいと最初から分かっていたので苦労も多かった。
しかし独自エンジンにすることで、シェーダを自由に書ける分やれることも多く勉強になった部分は多々ある。
まぁたぶん次作があるならUnreal Engineとか使うかもしれないが、、、。
今回シェーダは全部合わせると70を超すシェーダを製作した。
DirectX11では、描画すべてがシェーダありきで構成されており、点1つ書くだけでも必ずシェーダを通さないといけない。
いわゆるVS→PS(頂点シェーダー、ピクセルシェーダー)での描画である。
VS側で画面のどの座標に書くかをワールド座標などを取得し、PS側へ渡し、PS側で実際の画面への描画を行う。この際に、PSで計算を行い、影や効果などを求め、最終的に合成し出力を行う。
今回シェーダー以外にもボーンシステムによるキャラアニメーションも独自実装している。
mixamoでモーションデータは使用させて頂いたため、かなり工程は省けたが、ブレンダーでの融合がなかなか上手く行かなかったり、ボーンのスキニング計算によるメッシュ座標データの再計算に戸惑ったりといろいろあった。
特に今回のQullusrent3ではキャラに約20万頂点、8万以上の三角形が存在するわけで、アニメとなると、その20万頂点の座標をリアルタイムで計算し反映させないとアニメにならない。
ボーンデータから、次のアニメフレームを取得し、アニメフレームに沿ったウェイトを4ボーンで計算を行い、その結果をスキニング計算により20万頂点の座標を更新し、アニメとして成り立たせる必要がある。
最初これらをCPUで行っていた。GPUが結構大変そうだったからだ。
しかしデバッグでCPUスキニングを行うとめちゃくちゃ重いという欠点があった。そのため、最後にはGPU側へ移すことにより高速化を果たすことに成功している。
また、画面外判定や、描画順でのソートなどできる限りの最適化を行うことでステートメントマシンであるDirectX11のステートの数をできるだけ減らし、処理速度を稼いでいる。
そのため、今まで60fpsで作っていた物を120fps化させることも可能となり120fpsの精度で動かせている。
ノートPCなどでは40fpsくらいまで落ちはするが、60fpsで作られていた当時から見ると、倍の120fpsで見ているため、全体的に速くなったように思われる。
まぁ。倉庫番風パズルゲームでそこまで凝るのはどうなのかとも思ったが、どうせ作るなら、綺麗な方がいいし、高速な方がいい。
特にタイムアタックっぽい経過時間があるので、できるだけ軽くでも綺麗にを目指して今回作ってみた。
一応HDRにも対応はしているが、半透明形式であるEXR形式には対応していない。HDR拡張子には対応させたが、半透明の方はlibファイル作成がうまく行かず挫折し、pngファイルを内部でチューニングする方法を取っている。

BGMについても書いておこうと思う。
2年前のリファイン前のバージョンでは、SD-90を用い、Singer Song Writer 10にて、作曲を行った。
今回リファインするにあたりBGMも適用範囲だと考えた。
そこで、DAWで有名なCubaseを購入し、音源インストゥルメンタルもいくつか正式版を購入した。
Singer Song Writerで作ったものをmidiデータとしてはき出し、それをCubaseで読込、音色やパートの増減、微調整を行った。
DAW自体使うのが初めてで何度も音色や雰囲気などを変えてリリースの度にBGMの雰囲気が変わっていた。
タイトルやエンディングを含め全12曲の作成を終え、効果音も少しだけ置き換えたりし、私の中ではリファインたるものになったと思っている。
おまけでMIDIデータを苦労しながらmmlに変換させ、FM音源(YM2608)もおまけとしてモードを追加した。

バグはさすがに200万文字あるソースでないとは言い切れないが、リファインとしては満足となるものとなった。
あとはどうPRしていくかだが、、、、なかなかPRが上手く行かないのが現状ではある。


This time, I refined Qullusrent3 for DirectX11 and wrote all the shaders and such from scratch without using engines like Unreal Engine or Unity. I knew from the start that DirectX11 is notoriously difficult, so it was quite a struggle.
However, by using a custom engine, I gained the freedom to write shaders as I pleased, which opened up many possibilities and taught me a lot.
Well, if there’s a next project, I might probably use Unreal Engine or something…
This time, I created over 70 shaders in total.
In DirectX11, all rendering is built around shaders; even drawing a single point requires passing through a shader.
This is the so-called VS→PS (vertex shader, pixel shader) rendering process.
The VS side retrieves world coordinates and other data to determine where on the screen to draw, passing this to the PS side. The PS side then performs the actual drawing onto the screen. During this, the PS performs calculations to compute shadows, effects, etc., and finally composites and outputs the result.
Beyond shaders, we also implemented our own character animation system using a bone system.
Using motion data from Mixamo saved us a lot of work, but we encountered various challenges: the blending in Blender didn’t go smoothly, and we struggled with recalculating the mesh coordinate data due to the bone skinning calculations.
Particularly in this Qullusrent3 project, the character has approximately 200,000 vertices and over 80,000 triangles. For animation, those 200,000 vertex coordinates must be calculated and updated in real-time for the animation to function.
We needed to retrieve the next animation frame from the bone data, calculate the weights for the 4 bones based on that frame, and then use skinning calculations to update the coordinates of all 200,000 vertices to make the animation work.
Initially, we handled all this on the CPU because the GPU seemed quite strained.
However, debugging revealed a major drawback: CPU-based skinning was incredibly slow. Ultimately, we succeeded in achieving speedup by moving the processing to the GPU.
Additionally, we implemented every possible optimization, such as off-screen culling and sorting for drawing order, to minimize the number of states in the DirectX 11 state machine and gain processing speed.
This made it possible to upgrade content originally built for 60fps to run at 120fps with precision.
While performance might drop to around 40fps on laptops, compared to the 60fps standard when it was built, seeing it at double the speed (120fps) makes the whole experience feel faster.
Well… I did wonder if it was worth going to such lengths for a warehouse-style puzzle game. But if I’m going to make it, I want it to be beautiful and fast.
Especially since it has a time attack-like elapsed time feature, I aimed for something as lightweight yet beautiful as possible this time.
It does support HDR, but not the semi-transparent EXR format. I implemented support for HDR file extensions, but I gave up on the semi-transparent part because creating the lib file didn’t work out. Instead, I opted for a method that internally tunes the png files.

I should also mention the BGM.
In the version before refinement two years ago, I used an SD-90 and composed the music in Singer Song Writer 10.
When refining this time, I decided the BGM also needed updating.
So I purchased Cubase, a well-known DAW, and bought several official sound source instruments.
I exported the MIDI data created in Singer Song Writer, imported it into Cubase, and made adjustments to the sounds, added or removed parts, and fine-tuned details.
Since it was my first time using a DAW, I changed the sounds and atmosphere multiple times, so the BGM’s feel changed with each release.
I finished creating all 12 tracks, including the title and ending themes, and replaced a few sound effects. I feel this truly qualifies as a refinement.
As a bonus, I painstakingly converted the MIDI data to mml format and added an FM sound source (YM2608) mode as an extra.

While I can’t definitively say there are no bugs given the massive 2 million character source code, I’m satisfied with the refinement.
The next step is figuring out how to promote it… but honestly, promotion isn’t going very well at the moment.