Promete v2をリリースしました
Happy coding! 🎂
Promete v2 をずっと開発し続けていたのですが、この度ようやくリリースに至りました!
非常に多くの機能追加と破壊的変更、改善を行っているので、v1からは慎重な移行が必要となります。
ただ、現代はAIエージェントが非常に進化しています。時代に乗っかって、Prometeを用いたアプリケーション開発もAIを使いやすくなるよう改善しました。v1からv2への移行のためにAgent Skillを作ったので、v1 → v2 移行ガイドを参照して、ぜひ使ってみてください。
また、変更の全貌はリリースノートをご確認ください。
…さて、この記事では、具体的にどんな変更をしたのか、大きなものに焦点を当て、内部事情を掘り下げてお話していきます。
.NET 10への移行
Prometeでは、そのときの最新LTS版となる .NET をサポート対象とすることを方針にしています。今回の更新で.NET 10をサポート対象といたしました。
.NET 8は今年の11月にサポート切れちゃうんです。え、もうEOL…?3月に開発はじめて夏にリリースして、v1ユーザーが移行するまでの猶予に余裕を持たせるぞ…と思っていたのに…秋じゃん…
したがって、Promete v2への移行には、 開発中のアプリケーションも.NET 10への移行が必要になります。
NativeAOT / Trimming サポート
Promete v2では .NET NativeAOT を正式にサポートしました。この機能を使うと、C#で書いたアプリケーションをILではなく直接ネイティブコードにコンパイルでき、起動時間の短縮、メモリ領域の節約、ILと比較して逆コンパイル難易度を上げる…といったことができます。
また、NativeAOTの対応に必要なTrimmingという機能にも対応したことで、アプリケーションが使用していないPrometeの機能を削った状態で発行できるようになり、アプリケーション自体のファイルサイズを削減できるようになりました。
Prometeを最初に設計したときに、DIベースのプラグインシステムを採用した理由の一つに、このTrimmingとの相性の良さを挙げるほどでしたので、v2で念願の対応となります。
コマンドキューシステム
ノードの画面への描画は、これまではノードに対応したノードレンダラーというクラスが担当していました。
v2ではこの仕組みを書き直して、描画処理を「コマンド」という単位にカプセル化し、ノードがコマンドを毎フレーム発行する…という「コマンドキューシステム」を導入しました。
これにより、ノードの階層構造と、エンジンの描画パイプラインを構造上分離できるようになりました。また、テクスチャを描画する DrawTextureCommand が、同じテクスチャハンドルで連続している場合、エンジンは自動的にこれらのコマンドをまとめあげ、バッチレンダリングするようにしました。
また、LoadSpriteSheet で読み込んで分割したテクスチャは、ハンドルを共有するようになりました。スプライトシートとバッチレンダリングを組み合わせることで、ドローコールを大幅に減少させることができます。
フォントと文字列描画の作り直し
以前のTextノードは、内部的に文字列の描かれた画像を生成してそれをスプライトと同じ仕組みで描画していました。画像生成にはImageSharpの機能を用いていました。
この方式だと1文字変わるだけで文字列全体の描き直しが発生します。例えば長文を1文字ずつ表示するようなケースで、文章が長いほど処理落ちが起きやすい問題がありました。
v2では文字列描画を大幅に作り直しました。FreeTypeを用いて、フォントからグリフデータを取得し、1文字ずつのレイアウトとラスタライズをPrometeの描画コマンドに落とし込む改修を行いました。
これにより、フォントファイルの文字と他のテクスチャを混ぜる…といったこともできるようになったため、外字機能を追加することができました。ゲーム内通貨の独自単位の文字や、ゲームパッドのボタン画像などを文字列に混ぜて、NPCの会話に出現させる…なんてこともできます。
オーディオシステムの作り直し
v1では、音声データを表す AudioSource と、それを再生する AudioPlayer の2概念からなるオーディオシステムでしたが、AudioPlayerの責務を分離・整理するための作り直しを行いました。
細かい挙動の変更が気になる方はこちらのPRを見ていただくのが確実です。利用者向けには、この変更により次のようなことができるようになりました。
- リアルタイムなエフェクター(DSPフィルター)を差し込めるようになりました
- ディレイ、LPF、ディストーションをビルトインしています
- 自分でエフェクターを書くこともできます
- シーク(再生位置の変更)ができるようになりました
- OpenALの挙動に頼っていた「パン」をソフトウェア処理に書き換え、ステレオ音源に対してもパンが効くようになりました
- 複数のAudioPlayerを使用した場合の挙動は未定義でしたが、v2では安全に利用できるようになりました
フレームバッファ機能を磨き上げ
v1から利用可能だった FrameBuffer ですが、内部のノードはフレームごとに自動的に更新され、前フレームの内容は消去される…という挙動をカスタマイズできない制約がありました。
v2では AutoRender AutoClear プロパティを追加し、それぞれ無効化できます。また、手動でレンダリングをリクエストする Render() メソッドを追加し、任意のタイミングで描画をリクエストできます。より応用の幅が広がるでしょう。
また、画面全体をフレームバッファに一旦描画してから、その内容をスクリーンに描画するよう内部を変更しました。
シェーダーAPI
これまで、Prometeの内部に書かれたシェーダー以外を使うことはできませんでした(使うとしたら自前で描画処理を書く必要があった)。
Promete v2では、ノードの描画に使うシェーダーを差し替えてカスタマイズできるようになりました。
ShaderProgram クラスを用いてシェーダープログラムの読み込み・コンパイルを行い、Material クラスにuniform値と共にセットし、Node.Material プロパティに設定することで使用できます。
また、Prometeの画面全体がフレームバッファに描画されるようになりましたが、このバッファに対してもマテリアルを設定できるようにしました。これにより、ポストプロセスを取り入れることができます。
画像読み込みの内製化によるImageSharp非依存化
画像ファイルの読み込みに SixLabors.ImageSharp を用いていましたが、v2で内製に切り替えました。
PNGファイルの読み込みは .NET 標準の Zlib を用いることで簡潔に実装できるのもあり、外部ライブラリに頼るメリットが薄いと判断したためです。フォント描画でのImageSharp依存が無くなったため、この取り組みによって完全にImageSharpへの依存が無くなりました。
一方、これまで暗黙的にJPEGやGIFなどの読み込みもできる仕様でしたが、v2からは .bmp .png 以外に対応しなくなりました。別途、stb_imageなどを用いた他の画像ファイルの読み込みをサポートする Promete プラグインを開発しようかな…と思ってます。
Vulkanの対応(試験的)
PrometeはグラフィクスAPIを透過的に扱える設計にしており、もともとOpenGL以外の環境への移植を考えていました。
Promete v2で、実験的ではありますが、晴れてVulkanバックエンドを搭載しました。WindowsおよびmacOSでのExampleアプリの動作テスト、実際の開発中のアプリケーションへ組み込んでのテストも実施し、ある程度は動く段階です。macOS/MoltenVKでの動作がまだ少し怪しいかも…です。実運用にはまだ危ないですが、試してみてください。
v1のサポート方針について
GitHub: SUPPORT.md にもあるのですが、v1のサポート方針について。
v1は「延長サポート」へ移行します。今後、原則として機能追加は行いませんが、重大な不具合の修正対象となります。なお、v1のEOLは 2027/04/06 とします。
当初は.NET 8のEOLまでとする予定でしたが、思ったよりv2のリリースが遅れてしまったので、方針を変えました。
今後はv2が「メインサポート」となります。大きな機能追加はこのバージョンを対象とします。EOLは未定です。
いずれのブランチにおいても、Prometeのサポートは MITライセンスに伴い、無償で可能な限りの提供となります。 エンタープライズを対象とする高度なサポートは提供していないため、自己責任でご利用ください。
最後に
…だいたい大きな変更だとこのくらいですね。他にも細かなAPIの追加や変更が入っていますが、リリースノート以上のことを語ることがないので、一旦ここで区切ろうと思います。
v2の開発は2026年3月くらいから開始したのですが、思ったよりも長引いてしまいました。ベータ版はちょくちょく出していたのですが、なんだかんだバグを直しているうちに機能を増やしたい欲が出てきてしまい、リリースタイミングを見失ってしまった…というのが実情です。
Claude Codeのおかげで、わたし一人では思いつかなかった設計・実装方針の提案を貰えることが増え、v2の開発を通じてわたし自身のスキルもちまちまと向上してきました。コミットログを見ていましたが、当時はClaude Sonnet 4.6で開発していたみたいです。今は5.5が出てますから…AIの進化が早くて怖いです(笑)
相変わらず、わたしの好みに一辺倒なマイナーゲームエンジンではあるので、万人受けするとは思っていませんが…誰かに刺さったらええな~と思ってます。
v3の開発予定や何をやろうか…みたいなのを全く考えていないところではありますが、そろそろモバイルデバイスやWebAssemblyの対応にも舵を切りたいです。あとはmp3, opusなどのコーデックの統合を外部プラグインで実現したいですね。特にopusはvorbisよりも圧縮効率が良いので、本当は本体に取り入れたほうが良いのかもしれないですが…今のところ判断ついてないです。
あとは…3Dレンダリングに対応するか一生悩んでいます。2Dに特化、をウリにしている以上あまりやりたくない気持ちと、でも表現として取り入れると面白いこともある…っていう、心が2つある状態です……。3DやるならUnityで良くない?とも思う…
まあ、一旦はv2を無事リリースできたことを祝います!おめでとう!自分!
ということで、よければPromete v2、まだ使ったことがない方はぜひ試してみてください。既にv1をお使いいただいている方は、ゆるゆると移行していただければと思います。不具合があったらGitHub Issuesにてお願いします。
それでは。