自作Web3DライブラリRhodonite3年目の報告

# はじめに

この記事は [2022年WebグラフィックスAdventカレンダー](https://qiita.com/advent-calendar/2022/webgraphics) の２４日の記事です。
私 @emadurandal が毎年の報告として自作ライブラリの開発状況とその年の総括を行う記事となっています。

# Rhodoniteライブラリについて

[Rhodonite](https://github.com/actnwit/RhodoniteTS)はTypeScriptで書かれたWeb3Dライブラリです。
WebGL2に対応し、物理ベースレンダリングなどを含めた高度なレンダリングに対応しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/4b9d9739-ae3e-d809-03ab-3834a29e9d7a.png)

## インストール方法

npmで簡単にインストールできます。

```bash
$ npm install rhodonite
```

## 使い方

[WebGLを生で使うより](https://qiita.com/cx20/items/0597cdbccdd370e05956)、非常に短いコードで３Dを表示できます。

```typescript
import Rn from 'rhodonite';

// Rhodoniteの初期化
await Rn.System.init({
  approach: Rn.ProcessApproach.DataTexture,
  canvas: document.getElementById('world') as HTMLCanvasElement,
});

// キューブの生成
Rn.MeshHelper.createCube();

// レンダリングループ
Rn.System.startRenderLoop(() => {
  Rn.System.processAuto(); // キューブの生成を検知してキューブを描画してくれます。
});
```

より詳しい使い方は[こちら](https://github.com/actnwit/RhodoniteTS/wiki/%E3%82%A4%E3%83%B3%E3%83%88%E3%83%AD%E3%83%80%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3)をご覧ください。

# 今年の進捗

昨年末にv0.5.2だったバージョンも、今はv0.11.1までになりました。

## Rhodonite公式Editor、「Rhodonite Editor」を完全に一新

[Rhodonite Editor](https://editor.librn.com/)は、RhodoniteをベースにしたViewer/Editorです。昔はNuxt2(Vue2.js)で作っていたのですが、Next.js(React)で完全にコードを書き直しました。状態管理には[mobx-keystone](https://mobx-keystone.js.org/)を使っています。
RhodoniteのglTFExporterも昨年よりは実用的になり、Rhodonite Editorである程度glTFのオーサリングができるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/8fcb624a-79e8-5cc6-f4bb-20f0a48c819f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/72d32966-5cd9-68b2-496c-1af2bf5246b6.png)

## glTFのPBR（物理ベースレンダリング）系の拡張全てに対応した

現行のglTFのPBR拡張すべてに対応しました。これにより、昨年以上の高度なレンダリング表現が可能になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/b09ad396-af66-e95e-6a0d-9ec603dd117f.png)

以下はその一例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/17c35220-4c83-73b5-738f-1720a91da099.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/c0e29fd9-f4f9-6406-fa8c-52de0b3ecfaf.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/fff4d15b-68da-c539-1c7a-f8dd934c957c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/7d754f21-cc7e-f11a-34c8-3085668a36e5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/1727bea9-b591-bc76-d6d7-e82a033fcc09.png)

## Instanced Skinning Meshに対応

Instanced Skinning Meshに対応しました。インスタンス描画としてドローコールを発行しつつ、スキンメッシュもシェーダーで処理することを可能にしたものです。以下はVRMモデルを200体以上アニメーションさせているキャプチャです。アニメーションデータは個別に持っているので、キャラにそれぞれ別の動きをさせることも可能です。

Instanced Skinning Meshまでサポートすると、少しゲームエンジンっぽさが出てきますね（個人の感想です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/6f4bfc05-4a4f-86f0-43fc-3f77930f3c47.png)

## Wikiページの公開

Githubプロジェクト内に[Wikiコーナー](https://github.com/actnwit/RhodoniteTS/wiki/%E3%82%A4%E3%83%B3%E3%83%88%E3%83%AD%E3%83%80%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3)を作りました。昨年までマニュアルが一切と言っていいほどなかったのが最大の欠点でしたが、ある程度払拭できたのではないかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/81418bbc-0e60-623b-1c29-c6fc1c2a484e.png)

## Discussionページの公開

Githubプロジェクト内に[Discussion](https://github.com/actnwit/RhodoniteTS/discussions)のコーナーを作りました。まだ人は少ないですが、Issueを立てるまでもない質問などはこちらで聞けるようになりました。

## WebGL1のサポート廃止

思い切ってWebGL1のサポートを廃止しました。それまでは新しい機能を追加する際にも、WebGL1のことを考え、分岐コードを書いたり、WebGL1のGLSL仕様内に収まるような低速で回りくどいシェーダーコードを書かざるを得なかったりしたのですが、それが無くなり保守性が非常に良くなりました。

# 工夫したこと

## テスト、テスト、テスト

前作GLBoostとの最大の違いは、常に回帰テストを行う運用にしたことでリファクタリングを随時実行できる状況になったことです。
Github ActionでCIを回し、各種クラスのユニットテストと、Puppeteer(Chromium)によるヘッドレスレンダリングを用いたビジュアル回帰テストをプルリクエストごとに行っています。リアルタイムレンダリングの困りどころは、環境によって微妙にレンダリング結果が異なるためにビジュアル回帰テストが難しいことですが、RhodoniteではChromiumのソフトウェアレンダラ（SwiftRender）を用いることでどの環境でも一致したレンダリング画像を得られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/027e98ab-722c-8399-0fb1-1b9cc5f595ae.png)

Rhodoniteも開発開始から早４〜5年が経とうとしていますが、テストに裏打ちされたリファクタリングを継続的に行っているおかげで今もコード負債は抑えられ、設計の改善を継続できています。

# 今後について

## 描画ライブラリ/ビューアーからゲームエンジンへ

今まではglTF等の３Dファイルを表示するビューアーとしての立ち位置が強かったですが、今後はゲームコンテンツを作れる等のゲームエンジンらしい部分を作っていければと思っています。

## WebGPU対応

WebGPU対応はやはりやりたいですね。ただ、現在のRhodoniteはシェーダーからアクセスできるグローバルメモリとして使っている浮動小数点テクスチャのデータ効率があまり良くないので、その辺りの改善を行ってからになりそうです。

## 新しいライブラリの開発に着手した

私がこれまでやってきた３Dグラフィックスは主にWebGLでした。そのため表現できる範囲は実質、OpenGL ES 3.0でできることに限られます。さまざまな新しいCGの技法も、WebGLでは実装ができないことがあります。先端はDirectX12やVulkanですので、そうしたネイティブ系をやっていた方々に知識面・実装面で大きく遅れを取っていたことが長年のコンプレックスでもありました。

その状況を打破しようと、今年の11月から、C++による新しいライブラリの開発を始めました。名前は「Kairos」（カイロス）です。
DirectX12, Vulkan, Metalに対応したものにしようと思っています。

Rhodoniteの開発も続ける予定です。Kairosもあるので、開発リソースが分散されてしまうのが悩みどころではあるのですが。

# 最後に

今年の途中まで、CGへの興味が減退し、リベラルアーツ系に勉強のリソースの大半を費やしていた時期がありました。
そのこともあって開発にあまり時間を取れず、今年の進捗は若干少なめになってしまった気もします。

身を置く環境も変わり、自分の将来像やスキルセットをこれからどう構築していくか、模索の時期だったと思います。

しかし心機一転、C++で新しくライブラリを書き始めて気づきました。なんだかんだ言って、やはり私はライブラリ開発が好きなのです。基本的に気質がソフトウェアアーキテクトなのですね。

RhodoniteとKairosがこれからどうなっていくのか、今後もアドベントカレンダーで報告させていただければと思います。