lumino trail

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

開発状況 2018 #4

Lumino 8歳になりました。

多分そのくらい。

好きで作ることと惰性で作ること

開発に疲れて数週間音沙汰が無くなったと思いきや、以前より増した謎のモチベーションで GitHub に草を生やし始めます。 こんなことも半年スパンでかれこれ5回目くらいです。そういう人間なんでしょう。

一方の惰性の話。 Lumino は OSS ですが、やってることは多分全然オープンじゃないです。 というのも実際のところ「自分の成果物を他人と共有する」よりも「自分が勉強したことを実際にコードに落とす」ことに傾倒しすぎています。

まぁそのほうが楽しいからね。目標を文書にして開発ガイドラインを整えてリリースパッケージを準備するのは大変な仕事です。 だからだらだらと、勉強して、コード書いて、動いて、次。

勉強目的ならそれでいいし車輪開発も歓迎なんだけど、でもそうじゃないんだよ。そろそろちゃんと使える形でリリースしたい。

というよりまだ開発続けるつもりなの?

v1.0.0 までのロードマップを敷いて、そこにたどり着くまでは続けていきます。

一応、開発のモチベーションをメモしておきます。

やりたいこと

クロスプラットフォーム・マルチプログラミング言語で効率的かつ透過的に使える、デジタルアートなプログラマのための2D/3Dグラフィックスツールキットを作りたい。

あれこれなんかミッションステートメントのお題目でいい気がする。

作り始めた一番最初の動機は、RPGツクールスクリプトシステム、あれを C++C# でも使いたい!でした。すごいよ、あれは。

学ぶことの土台

そこそこの規模のソフトを組むというのはそれだけで学べることがあるわけで、Lumino の開発からは新しい技術を勉強するだけでなく設計の方法など多くのことを学んでいます。

今はそれでゴハン食べてるからそれはそれで Lumino 作って成功だったかなと思います。

Lumino の今後

開発状況をオープンにするには何をすればいいだろう?

  • スコープを決める
    • どのタイミングまでに何をやるのか、やらないのか(期間は決めないです。そのへん決めても本業しだいで予定通り時間はとれない)
  • とにかくまずは使える状態で公開する
  • 経過をアウトプットする
    • 進捗報告だけじゃなくて、そのローカルにため込んでいるメモ兼仕様書を公開するのじゃ。

とか考えつつ・・・

今のコードは v0.4.0 タグを以ってアーカイブします。

最初から完璧なドキュメントは用意できませんが、基本的なものを用意した後、ロードマップに沿ってコードをイチから入れなおします。

書き直すのではなく、コードに山ほど書かれていたりする TODO を潰したりテスト書いたりリファクタリングしながら再構築していきます。(戒め:異常系動作を詰めすぎない。どうしても逃げ道がなければ対策するが、それよりユーザーストーリーの満了を優先)

合間に、共有できそうな技術情報があればアウトプットしていきます。

また、バイナリパッケージは初版から公開していきます。まずは Nuget かな。

ゲームエンジンとしての機能はかなり先の実装になりますが、しばらくは粛々とタスクを消化していきます。

Note

ロードマップ https://github.com/lriki/Lumino/wiki/ProjectRoadmap

進捗状況 https://github.com/lriki/Lumino/projects/1

開発状況 2018 #3

ずっといじってる Chainer のほうですが、Model とか Updater とかの学習の土台ができてきたので、少しずつ集めていた 500 体くらいの 3D モデルをデータセットにして学習させています。 (今までは数体だったので過学習状態でした)

・・・が、これがまたとんでもなく時間かかっていて、ちょっと足踏み中。学習中は暇なのでジャヴァスクリプターしてます。

Lumino 本体はそんなに変更ないですが、ジャヴァスクリプターついでに Emscripten について調べてたりします。C++ コードを JavaScript に変換するアレ。

Core モジュールはほぼ変更無しでブラウザで動かせました。

ファイルIO 以外はね!!!

ずーっとネイティブアプリを相手にしてたのでこの辺戸惑いが多かったですが、まぁなんとかなるでしょう。

開発状況 2018 #2

相変わらず Chainer いじってます。 なので Lumino 自体の進み具合は微妙です。

SkinnedMesh 周りを作っています

SkinnedMesh は当面公開予定のないモジュールでしたが、今回のツールでポーズ付けたりする必要があるので作りこんでいます。

2月中はほぼずっとこれ。

f:id:lriki:20180228223118p:plain

言語バインダ自動生成を clang で置き換えています

SkinnedMesh 実装中の息抜きに、Lumino とほかの言語 (C,C#,Ruby など) をつなぐグルーコードの自動生成にお直し入れたりしています。

これまで自前のパーサ組んでましたがメンテするの限界なので clang に置き換えています。

開発状況 2018 #1

年末からずっと Chainer をいじっています。そのため Lumino の開発は停滞・・・するかと思いましたが、 3D な学習データの作成やボクセルマップのビューアを作るのにそこそこ都合が良かったので、その途中で必要になった機能や不具合の修正がいくつか入っています。

MeshResource クラスがインデックスバッファのフォーマットを自動検出できるようにしました

メッシュを扱うとき、メッシュコンテナや LOD など、効率的な描画のためには考えなければならないことがたくさんありますが、MeshResource クラスはそういったメッシュ構造の最小単位です。 この人は addBox() や addSquare() といった、形状を動的に追加できるメソッドを持っていますが、これまでは 16bit インデックスバッファの限界までしか追加できませんでした。

Box 2000 個も使えないんじゃボクセルマップで使うのはキツイです。ということで拡張しました。

ファイルをウィンドウへドラッグ&ドロップできるようにしました

ビューアならこれくらいできて当然だよね?ということで。 インターフェイスWPF と Qt をまぜまぜしたような感じです。

UIMainWindow* window = Engine::getMainWindow();

// D&D 許可
window->setAllowDragDrop(true);

window->connectOnDragEnter([](UIDragDropEventArgs* e)
{
    if (e->data()->hasDropFiles())
    {
        // ファイルなら受け入れる
        e->setEffect(DragDropEffects::Copy);
    }
});

window->connectOnDragDrop([](UIDragDropEventArgs* e)
{
    for (auto& file : e->data()->dropFiles())
    {
        // Drop されたファイルパスを表示
        Console::writeLine(file);
    }
});

connectOn~ は少し冗長を感じるので += 演算子をサポートするかもしれません。

時計回りの頂点並びをポリゴン正面方向にしました

Lumino は左手座標系です。

方向 向き
X方向 右が正
Y方向 上が正
Z方向 奥が正

回転方向などなど全部「左」に統一するため、面方向も左ねじにしました。

内部文字コードの統一と Mac 対応中

UTF16 に統一しようとしています。char でも wchar_t でもなく、char16_t です。Qt や Cocoa に倣う、という感じで。

個人開発レベルのゲームエンジンでこんなことやるのは正気を疑われそうですが、和製のライブラリということでエンコーディング周りは元からかなり気を使って作っていました。 Core モジュールのユニットテスト通せた今のところ、特に大きな問題は出てないです。

このまま上手くいければいいなぁ・・・。

今後の予定

Lumino はゲームエンジンだけではなく一般的なグラフィックス系アプリのフレームワークとしての利用も想定しています。 とはいえソレをメインで開発しているわけではないので、細かい TODO が山ほど溜まってしまいました。

これの消化ばかりに時間を使うわけにもいかないので、Mac 対応の途中でお亡くなりになってるユニットテストを通したら次のお試し版を出したいです。

師走と作業報告の候

一年の振り返りとかやろうとしたけど、意外と予定が詰まってしまいました。 あとでちゃんとやろう。・・・とか言いつつ積んでる記事が4つくらいあった気がします。

ひとまず、いつもの報告です。

イチからシーンを構築してレンダリングし、png に保存できるようにしました

ゲームじゃなくてツール開発向けの機能です。

ゲーム用のレンダリングは Engine クラスにいろいろ隠蔽されていますが、それを使わないでレンダリングできるようにしています。

コードはこんなイメージ。

auto world = newObject<World3D>();

// スキンメッシュのコンポーネントを作る。
auto skinnedMeshComponent = SkinnedMeshComponent::create("3Dモデルファイル");

// スキンメッシュを表示するためのオブジェクトを作り、コンポーネントを追加した後ワールドに追加する。これでレンダリングされるようになる。
auto skinnedMeshObj = newObject<WorldObject>();
skinnedMeshObj->addComponent(skinnedMeshComponent);
world->add(skinnedMeshObj);

// メッシュの境界ボックスを取得しておく。
Box aabb = skinnedMeshComponent->getSkinnedMeshModel()->getBoundingBox();

// 平行投影カメラを作る。境界ボックス全体を視界とする。
auto camera = OrthographicCamera::create();
camera->setOrthographicSize(aabb.height);
camera->setNearClip(0);
camera->setFarClip(aabb.depth);
camera->setPosition(Vector3(aabb.center.x, aabb.center.y, aabb.center.z - (aabb.depth / 2)));
camera->lookAt(aabb.center);
world->add(camera);

// 描画先レンダーターゲットを作る。
auto renderTarget = RenderTargetTexture::create(512, 512, TextureFormat::R8G8B8A8);

// OffscreenWorldRenderView を作り、レンダーターゲットと、そこへ描画するワールド、視点(カメラ) をひとつにまとめる。
auto ofs = newObject<OffscreenWorldRenderView>(world, camera->getCameraComponent());
ofs->setRenderTarget(renderTarget);
ofs->setBackgroundColor(Color::White);

// レンダリングして画像に保存
ofs->render();
ofs->getRenderTarget()->readSurface()->save("img.png");

f:id:lriki:20171231233710p:plain

シェーダがスフィアマップ対応してないとか、ちょっとまだレンダリングおかしい。

2Dイラストからドット絵アニメを自動生成したい

企画中のゲームで、パターン多めのドット絵アニメを作ろうとしています。

そんなところで、前々からディープラーニング勉強してみたかったのでこんなプランを考えました。

  1. 2Dイラストをディープラーニングで3Dボクセルマップに変換
  2. 3Dボクセルマップからメッシュモデル作成
  3. メッシュモデルにボーン入れ
  4. 必要に応じてSD化
  5. 普通にスキンメッシュアニメーション
  6. フレームをキャプチャ
  7. 手動で仕上げ(あるいは画風変換)

フォトスキャンのイラスト版みたいなイメージ。 あらゆる形状のモデルを、ってのは多分ものすごく難しいから、まずは人型で行ってみます。

んで第1版。

f:id:lriki:20171231233731p:plain

前途多難。

霜月と作業報告の候

光かわいい。

物理ベースレンダリングを標準サポートします

f:id:lriki:20171201005215p:plain

動機:マテリアルとライトがシンプルに作れるから

こんなのこんなの はめんどくさいよ!とっつきにくくなるだけだよ!

とか言いつつ光学をかじっています。

ライトのインターフェイスを仕上げました

インターフェイスAPI とはすなわち、ユーザーとの約束である。 これを決定し、将来にわたってメンテナンスを続けることはつまり鎖であり、それは信頼である。

  • AmbientLight
  • HemisphereLight
  • DirectionalLight
  • PointLight
  • SpotLight

どこか で見たことあるようなクラスたちだね!

物理ベースレンダリング用なので、プロパティもほとんど同じようなのがいます。

ソフトシャドウ作ってます

今のところ DirectionalLight に限り、影を落とすことができます。

FXAA 作ってます

MSAA よりちょっと高速かも。ただ、なんか汚い気がする。

まとめ

Lumino っていう名前らしい機能やっと作ってあげられそう。

ていうか早くブランチ閉じて記事書く詐欺を解決して次のテスト版準備しないと・・・。

神無月と作業報告の候

よくない。とっても良くない。

主に進捗が。

またブランチ1ヶ月以上のばしてるよ。

よくない。

SSAO

ほい

f:id:lriki:20171031213352p:plain

後で記事書く。複雑だから。

Clustered Shading

ほい

f:id:lriki:20171031213338p:plain

後で記事書く。複雑だから。

CornellBox

ほい

f:id:lriki:20171031213420p:plain

これは複雑じゃないかな。

レンダリングパイプライン

先月「Deferred Shading はやらない」とか言ってたけど、SSAO 作る途中で似たような仕組みをやっていました。

その結果、クラシックなライティングでも Clustered でも Deferred でも、その子たちの差し替えとかハイブリッドとかついでにカスタムシェーダもやっちゃうよとか なんかもうなんでもできそうなパイプラインが見えた気がするので、いいかげんこいつの fix にかかるよ。 (と言っても書きなぐりゴミコードが多いから時間かかりそうだけど・・・)

これ以上求めるならコンシューマなつよいゲームエンジンとか使ってねの限界が見えた気がします。 だから進捗悪くなったのだろうか。燃え尽き症候群的な。ラスボスの前でセーブして積んでる的な。

よくない。よくないよ。