lumino trail

ゲームエンジン作ってます。Github:https://github.com/lriki/Lumino Twitter:https://twitter.com/lriki8

開発状況 2019 #7

5~6月は投稿を完全に忘れるくらいお仕事が盛り上がっていました。

実は5~12月くらいで1本ゲーム作る計画を立てて、それに沿って Lumino の開発を進めてたりしたのですが、いきなり仕事の影響で出鼻をくじかれてやる気無くしてた感じです。

マルチプログラミング言語

次の v0.9.0 のメイン機能です。

まず、こんな感じでマクロを使って C++ のクラスやメソッドをタグ付けしておきます。

LN_CLASS()
class Sprite : public VisualObject
{
    ...
};

このコードを clang で解析して、

  • C++ クラスをラップする Flat C API を自動生成
  • さらにそれをラップするクラスライブラリを各言語ごとに自動生成

みたいなことをします。

まずは Ruby をターゲットにしていますが、次のようなコードで、画像を表示することができます。

require 'Lumino'

Engine.initialize

texture1 = Assets.loadTexture("img.png")
sprite1 = Sprite.new(texture1)

while Engine.update do
end

Engine.finalize

こんなふうに、C++ インターフェイスを他の言語に公開するのがすごく簡単になります。

メソッドのオーバーライドやイベント通知もサポートするよ。

エディタ

ゲーム開発を始めて最初のころは「コードだけでもなんとか行けるでしょ」とか思っていましたが、シーン作り出すあたりから限界が見えてきました。 やっぱり微調整のイテレーションオーバーヘッドが主な理由です。

というところで、まずは GUI フレームワークの検討から始めました。

要件は、

ということで、候補は次の通り。

  • Qt Quick
  • Qt Widgets
  • imgui
  • LuminoUI (自作)

Qt Quick

そこそこキレイなアプリが作れるフレームワーク。ロジックを C++、ビューを QML (JavaScriptライク) で書きます。

レガシーなフレームワークありがちな、細かいレイアウトの調整ができない問題がクリアされていて、見た目をかなり自由に作ることができます。

ネックは情報量でしょうか…。バグか仕様かわからずコードまで読みに行ったりしてました。

もうひとつはグラフィック固有の問題ですが、OpenGL などネイティブグラフィックスAPIの呼び出しはレンダリングスレッドで行う必要があるため、 Lumino のような外部のレンダリングライブラリを取り込むときは細心の注意が必要です。

これに対応するため Lumino のマルチスレッド対応とかやってましたが、Qt API (妙なところに const 付いてたりとか) に合わせこむため余計にクラス増やしたり、モノによっては本体のコード追ったりするのに疲れて断念しました。

っていうか、よく考えたらエディタ拡張を書きたいときでも View 作るのに QML 必須になってしまうか…。

Qt Widgets

枯れていつつも長く使われているのは重要な長所です。でも空ウィンドウ開くだけでメモリリークするのはちょっと心に悪いです。

簡単な UI 作るのにはすごく素直に動いてくれるので、Qt Quick に対しては長く使っていました。Ruby ラッパーとかからも呼べるし。

レンダリングライブラリの統合も、OpenGLWidget を使うのもいいし、ネイティブのウィンドウId取ってそこに書くのもいいし、簡単でした。

ただ、ゲーム系というかエンタメ系というかの GUI ツールって結構独特なウィジェットが多くあります。それに耐えられるのか…ってところで、 「結局 QPainter で直書きするくらいなら Lumino で書きたい」みたいな魔が差して断念。

imgui

これの検討を始めるころには、Lumino の UI モジュールがそこそこいい感じに動くようになってきたので、 ものすごく悩んだのですが採用は見送りました。

主な理由は UE4 が Slate を自作した理由とほとんど同じです。 https://docs.unrealengine.com/en-US/Programming/Slate/Architecture/index.html

それでも便利なのは変わらないので、デバッグ用途では使っていくかも。

LuminoUI (自作)

死ぬわアイツ

正直 100% ゲーム用の UI フレームワークとして作っていたので、エディタで使うつもりはありませんでした。

しかし、色々とアレもやりたいコレもやりたいを詰めていった結果、徐々に レイアウト、スタイリング、アニメーション、イベントシステム周りが WPF+HTML(CSS)+Qt みたいなかなりガチ仕様になってきていました。

コンポーネントは圧倒的に足りてないけど、ベースが結構いい感じになってるので、シンプルなエディタなら作れるのでは?ついでにほかの言語のラッパーも簡単に作れるし、エディタ拡張もLuminoだけで完結するし。 …と自惚れた結果、全部 Lumino でやるという(多分地獄の)道を選ぶことにしました。

f:id:lriki:20190731203504p:plain

見た目は雑なシーンビューアですが、ゲームジャンルごとに必要そうな小エディタ(拡張機能)を組み合わせて、作りたいゲームに合わせたエディタを構築できるような仕組みを考えています。

3Dシーンエディタ・2Dモーションエディタ・RPGイベントエディタを組み合わせて、2.5D RPGを作ったりとか。

Effect

ゲーム作りを始めたので、エフェクト出せる仕組みが欲しくなりました。

Lumino はパーティクルシステムを持っていますが、もっと凝ったエフェクトも出せるようにしたいな、ということで Effekseer の組み込みを始めています。

で、Lumino はちょっと前に Vulkan への実験的な対応を行い、開発中は基本的に Vulkan で動かしていますが、Effekseer が Vulkan 対応してない!という状態でした。

対応を待つか、Lumino 側でラップするか… とかいろいろ考えていましたが、せっかくなので Effekseer の本流にコミットすることにしました。

GitHub は長く使っていますが、今回初めて、ほかのプロジェクトへプルリク送る運びとなりました。

f:id:lriki:20190731204358g:plain

Graphics

ロードマップ上では fix 済みのモジュールなのですが、Vulkan 対応を受けて色々思うところがあったので、少し API を変えようとしています。

具体的には RenderPass と CommandList の実装です。

ねらいはこんな感じ。

  • 描画速度向上
  • GPU 機能の並列実行 (特に並列コンピュートシェーダ)
  • 他のアプリへの組み込み易さ

他のアプリへの組み込み

今の Lumino は Graphics や Audio など様々なモジュールがひとつになった巨大なライブラリですが、そのうち小分けにして配布しようと思っています。

  • クロスプラットフォームな3D描画やりたいときは LuminoGraphics 使えるよ
  • オーディオグラフ作りたいときは LuminoAudio 使えるよ
  • ステートフルな UI 作りたいときは LuminoUI 使えるよ

みたいな。

・・・自分のリソース絶対足りてないなぁ

開発状況 2019 #4

平成最後ですがいつも通りです。

master ブランチにマージした CI ビルドが終わったら 0.8.0 リリースです。この記事投稿してる時も多分どっかのサーバでガシガシやってると思います。

Graphics

OpenGL ドライバで fix です。API は DirectX11 に近い感じで着地となりました。

シェーダは HLSL5 で書いて、Web やモバイルでも動かせちゃったりします。

Vulkan は Experimental ですが一応使えます。GPU が対応していれば・・・。

チュートリアル

未完成 & 穴だらけですが、チュートリアルを作る気持ちだけ公開しました。

まだまだ変更入れたい予定です。

今後について

次の 0.9.0 はトランスコンパイラの実装です。clang 使ってコード解析してラッパーを自動生成するやつです。

ただそれやる一方で、ちょっとゲーム1本くらい作ろうと思います。C++で。

アクションにするかローグライクにするか、色々ネタがたまってるからどうなるかは計画中ですが、できればコードは OSS にして Lumino の Example project にしてみたいと思います。

開発状況 2019 #3

今月は主に、チュートリアルで使う2D物理演算とUIシステム、それと Vulkan 対応を進めていました。

Font

これまではフォントを使うときは必ずプログラムのどこかでフォントファイルを登録する必要がありましたが、 mplus フォントをビルトインフォントとして使わせていただくことにしました。

ただやっぱりファイルサイズが大きいので、ひとまず Lumino をライブラリ単体として使うときは ASCII サブセットのみの対応としておきます。 (lumino-cli を使ってデプロイするときは日本語ちゃんと使えるように Asset をくみ上げる予定)

Rendering

UI要素を描画するために必要な機能をいくつか追加しました。 特に、背景と枠。

Animation

プロパティアニメーションを実装しました。 ただ当初はチュートリアルで使おうと思っていましたが、多分直近では不要になりそうなのでちゃんとテスト書いて公開するのはちょっと先になります。

Physics

2D物理システムについて、レイキャストやコリジョンコールバックなど、ゲーム開発に最低限必要な機能を実装しました。 ドキュメントが全然足りてないのが最大の問題・・・。

Graphics

Windows では Vulkan がかなりいい感じに動くようになってきました。 次は macOS, Android あたりで対応したいけど、0.8.0 に向けての Vulkan 対応は Graphics モジュールのモダンAPI対応によるインパクトを見るのが主な目的なので、Windows 以外はもう少し先です。

今後について

Graphics モジュールの API がほぼ固まったので、0.8.0 リリースに向けて仕上げていきます。まぁ、主にユニットテストとドキュメントですが。

Vulkan をどうやって使ったかはどこかでブログ書いておきます。っていうか、残しておかないと自分が忘れる・・・。

開発状況 2019 #2

ようやくといいますか、やっとといいますか、チュートリアルを書き始めました。 Lumino 全体を浅く触りながら、2D のアクションゲームを作るものです。

実際に書いてみるとゲームエンジンとしてちょっと足りてないところが出てきたので、今月のコミットはいろいろなところに手が入っています。

Audio

0.4.0 以降、とりあえず音鳴ったわーいで止まってたものを、ちゃんと BGM と SE 同時再生できるようにしたり、キャッシュを実装して効率よくたくさんの SE ならせるようにしたりしてました。

新しい Audio システムは WebAudio ライクなノードベースで柔軟にエフェクト掛けられるすごいやつですが、このへんの API をちゃんと決めてテストできるのはまだ先になりそうです。

Physics

Box2D を組み込んで、2D シーン用の高速な物理演算システムを作りました。

Unity などのゲームエンジンと Box2D では API にかなり差がありますが、Lumino は 3D と同じく Unity 寄りに実装してあります。なので、単なる薄いラッパーではないです。

UI

画面に文字を表示するための UITextBlock を実装しました。使い方は WPF の TextBlock をイメージしています。

というより、Lumino の UI モジュールは全体的に WPF をイメージしたスタイリングやレイアウトシステムとなっています。

Animation

プロパティアニメーションを実装途中です。スキンメッシュアニメーションと同じようなインターフェイスでオブジェクトのプロパティを変更できるようになります。

とりいそぎ、チュートリアルでのスプライトアニメーションで使う予定です。

Graphics

UITextBlock の実装のため、スプライトベースのテキストレンダリングを実装しました。0.4.0 以降はとりあえずテクスチャへのBlitだけで実装していましたが、これからはリアルタイムに描画できるようになります。

あと、Vulkan を引き続き組み込み中です。一応次の 0.8.0 は Graphics モジュールを固めて出す予定なので、100% ではなくてもせめて公開 API へのインパクトの有無くらいはつかめるくらいには入れておきたいです。

今後について

チュートリアル完成と Vulkan 組み込みが二大柱です。 次の 0.8.0 はこの 2 つを目標にリリース予定です。

開発状況 2019 #1

いつのまにか、このブログを始めてから2年経ってました。 コードはすごく変わりましたが、機能的にはほとんど進みが無いように思います。 リファクタリングやりすぎ案件の事例です。

v0.7.0 リリース

こっそりしてました。

ただ、HLSL シェーダをいろいろなターゲット向けにトランスパイルする機能を仕上げただけなので、これだけで何かできるってわけではありません。なのでこっそり。

Graphics

Vulkan の対応を進めています。

これまではずっとレガシーDirectXOpenGLでした。

しかし、次の 0.8.0 で fix したい Graphics 機能のために、少なくともモダングラフィックス API の「クセ」みたいなものをちゃんと知った上で実装しないと また大きな作り直しをしそうなので、ここで対応することにしました。

Mesh

ふと、丁度一年くらい前に作っていたボクセルモデルの自動生成をまた進めたくなったので 3D 周りに手を入れ出しました。 ただ Vulkan 対応がすごく重かったので、こっちはとりあえず .obj と .pmx を読めるようにしただけです。

今後について

Vulkan がんばります。

開発状況 2018 #12

リポジトリの Readme で「実際にゲームを作りながら」と言ってますが、ぼちぼちゲームを作るための機能がそろってきたので制作を始めました。

と言っても何年も前にプロト公開した作品のエンジン部分を乗せ換える作業がメインです。

あとはコミットログを遡って、今月やったことを思い出してみます。

Audio

Sound クラスと GameAudio クラスを実装しました。 基本的な使い方は 0.4.0 のものと変わりませんが、内部実装は Web Audio ライクなノードベースのサウンドシステムの上に作られています。 ので、今後はエコーやノイズなどのエフェクトを適用できるようなインターフェイスを追加する予定です。

あと、Ogg vorbis ファイルを再生できるようにしました。

Graphics

Texture2D クラスに、

  • 単色塗りつぶし (clear)
  • 他のテクスチャからのビットマップ転送 (blit)
  • 文字列描画 (drawText)

を追加しました。 プログラム内での簡易的なテクスチャ編集に使います。

Tilemap

2D ゲームのマップなどでよく使われる機能です。 ロードマップ にはありませんが、ちょっと2Dなゲームを作りたい気持ちが出てきり、↑で制作中のゲームで必要になってきたりしたので実装中です。

ImageEffect

いわゆるポストエフェクトです。Unity の ImageEffect と同じです。 今回は2つ作りました。↑の動画でも使っています。

ToneImageEffect は画面全体の色調を調整します。セピア調のイメージを作ったり、フェードイン・フェードアウトの演出に使用できます。

ScreenBlurImageEffect は前回フレームの描画内容を重ね合わせる単純な方法で画面全体のブラーを表現します。

Scene

主にデバッグ用に、マウスでカメラを操作するための CameraOrbitControlComponent を実装しました。

これは Camera オブジェクトにアタッチして使う Component です。以下のようにするだけでぐりぐりできます。

Engine::mainCamera()->addComponent(CameraOrbitControlComponent::create());

Physics

bullet ライブラリをビルドシステムに追加しました。 とりあえず PhysicsWorld を作れるようにしただけで、まだ何もできません。

Shader

実際に本番環境で動かすと出てくるバグからはどうしても逃げられないようで、 あとはドキュメントだけで次のバージョン出せるぞ!とか思っていたら、↑で制作中のゲームで問題が出てきました。 バグっていうか単純な検討不足だったんだけど・・・。

とりあえずこんな↓対策にしました。

今後について

Shader モジュールに対してちょっと変則的な実装を加えたので、1月一杯くらいは様子見です。

他はゲーム作りつつ実装を続けていきます。

開発状況 2018 #11

次verではシェーダコンパイラの対応を行う予定ですが、相変わらず別モジュールの実装に浮気中です。

といっても fix できたものも無いので、コミットログをざっとさかのぼります。

Sprite

2D イメージを表示するためのアレです。

0.4.0 では配置する座標空間が異なる Sprite2D, Sprite3D がありましたが、 それぞれ

  • Sprite2D → UISprite
  • Sprite3D → Sprite

となりました。

2D 系は基本的に UI モジュールに押し込める感じで、ほかにもサフィックスとして 2D,3D とついていたものは同じように変更されます。

ImageEffect

適用先が増えました。

  • Camera
  • OffscreenRenderTarget
  • Window 全体
  • UIサブツリー

いろいろなところにエフェクト掛けられるようになります。

Archive

画像や音声など、配布するリソースファイルを1つのファイルにパックするアレです。

抽出防止のために暗号化掛けますが、以前のものはライセンスのソースがなんかパッとしなかったので zlib を参考に書き直しました。

ちなみに zip 圧縮も掛けようとしましたが、よく調べてみるとランダムアクセスが困難だったので、圧縮はやめました。

Audio

0.4.0 で公開していた Sound クラスとバックエンド (XAudio, OpenAL など) の間に、Web Audio ライクなノードベースのシステムを作りました。

これでかなり細かくサウンドエフェクトの適用個所を制御できるようになります。エミッタ個別でノイズ掛けたり、シーン全体にエコー掛けたり。

0.7.0 (Shader) について

前回の内容で、各プラットフォームの動作確認中です。 あとは

  • macOSiOS で動作確認
  • テンプレートプロジェクトの修正
  • ドキュメント更新

あたりかな。