8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

グラフィックス全般Advent Calendar 2024

Day 25

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

Last updated at Posted at 2024-12-24

はじめに

 この記事はグラフィックス全般Advent Calender25日目の記事です。
 私、@emadurandalは自作のWeb3Dライブラリを開発しておりまして、毎年アドベントカレンダーで一年の報告をしております。

 今回は、Rhodoniteという自作ライブラリの5年目の報告ということで、記事を書かせていただきます。

今年の振り返り

 一昨年以降、やる気の波の上下が激しく、今年もだいぶ怠けてしまった部分がありますが、昨年よりは多少できたことは多かったかな、と思います。

Rhodoniteライブラリについて

 RhodoniteはTypeScriptで書かれたWeb3Dライブラリです。
 WebGL2とWebGPUに対応し、物理ベースレンダリングなどを含めた高度なレンダリングに対応しています。

image.png

インストール方法

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

$ npm install rhodonite

使い方

 WebGLを生で使うより、非常に短いコードで3Dを表示できます。

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(); // キューブの生成を検知してキューブを描画してくれます。
});

 より詳しい使い方はこちらをご覧ください。

Rhodonite Editor

Rhodonite Editorというビューアーもあります。npm installして試すのなんてめんどいという方は以下のURLにアクセスして、画面にglTFファイルとかVRMファイルとか放り込んでみてね(´・∀・`)

今年追加した機能

WebGPU対応

WebGPUに9割ほど対応しました。1割まだなのは、影生成とか一部まだ実装できていないところがあるんですが、まぁ大体は動くようになりました。去年は全然モチベ上がらねぇ、とか言ってましたが、今年は少し自分を褒めたい。

肝心のパフォーマンスですが、WebGPU版はWebGL版よりも相当高速(レンダリング処理が3~4倍高速)に動作するようになりました。

描画パフォーマンスの大幅な改善

WebGL実装、WebGPU実装ともに大幅な描画パフォーマンスの改善を果たしました。WebGL実装は昨年時と比べて約4~5倍(ドロー時間1/5~1/4)速くなっています。WebGPU実装はさらにその3~4倍ほど速くなっています。

ライブラリ全体に渡って地道な最適化作業を続けた結果です。Three.jsやBabylon.jsと遜色ない描画速度になったと思います。

描画時間が1msecを下回るのを見ると気分が良いですね。

image.png

ブルームエフェクトをサポート

ブルームエフェクトをサポートしました。光が溢れ出るような効果を演出します。野外シーンなどでだいぶ雰囲気が出るようになりました。

image.png

glTF拡張、KHR_materials_emissive_strengthをサポート

emissive(自己発光)パラメータで1.0以上の値をサポートするための拡張です。同拡張では、1.0以上が設定されている場合はブルーム処理等の対象とすることなどが示唆されています。
(Rhodoniteの場合は1.0以上でなくてもレンダリングの結果として1.0以上の輝度値になればブルームがかかるようになっていますが)

image.png

VRのMultiView拡張 (OCULUS_multiview/OVR_multiview2)をサポート

WebVRレンダリングを高速化するMultiView拡張に対応しました。これは、左目・右目の描画処理を一度に行うことによりパフォーマンスを改善するものです。

image.png

ノードベースシェーダーのリファイン

以前からノードベースシェーダーの仕組みはありましたが、UI画面として頂点シェーダーとフラグメントシェーダーが分かれていました。どうしようか迷いましたが、他の多くのエンジン・ライブラリのノードベースシェーダーが同一画面で頂点シェーダ・フラグメントシェーダーを扱っているので、Rhodoniteもそれに合わせることにしました。

この作業が意外と大変で、頂点シェーダー側のノードをフラグメント側のノードに繋げた際、その間をうまくVaring変数で橋渡ししてあげる必要があります。その辺りの内部処理の実装は骨が折れましたが、だいぶ良い仕組みに落ち着いたと思います。

トーンマッピングをサポート

トーンマッピングをサポートしました。大体のメジャーどころは対応しています。
Khronos PBR Neutralが程よく彩度を保ってくれるため、これをデフォルトにしようかな? と思っていたのですが、HDRブルームとの相性が悪そうという意外な特性があったことがわかり、結果的にGT ToneMapがデフォルトになりました。

  • Reinhard
  • GT ToneMap
  • ACES Filmic Tone Mapping (Narkowicz)
  • ACES Filmic Tone Mapping (Hill)
  • ACES Filmic Tone Mapping (Hill - Exposure Boost)
  • Khronos PBR Neutral

image.png

IBLプレフィルタリング処理をサポート

IBLプレフィルタリング処理をサポートしました。以前から一応サポートはしていたのですが、それまでは別の方に開発していただいたものを使わせていただいていました。そのバージョンは輝度変化の大きな部分でFireflyアーティファクト(ところどころに明るい粒々が生じるアーティファクト)が生じることもありました。

今回は、新規にIBLプレフィルタリングを自前で実装しました。自前、と言いつつ多くの部分をglTF Sample Rendererの実装を参考にしていますが💦

おかげさまで、とても綺麗なプレフィルタリング結果が得られるようになりました。

HDR画像をお持ちの方は、Rhodonite Editorに.hdrファイルをドラッグ&ドロップしてみてください。HDR画像がプレフィルタリングされ、IBL(ライティング)処理に使われます。

FinalizationRegistryによる自動破棄

テクスチャクラスのオブジェクトがどこからも参照されなくなり、GCで破棄される場合に、内部で保持しているWebGL/WebGPUテクスチャリソースも自動解放されるようにしました。

これには、モダンブラウザでサポートされているFinalizationRegistryという機能を利用しています。

FinalizationRegistryについてはこちらの記事をご覧ください。

この仕組みだと、テクスチャクラスがGC対象(どこからも参照されていない)にならないと内部テクスチャリソースが解放されないため、テクスチャクラスオブジェクトをライブラリ内部で参照している箇所の多くをWeakRefによる弱参照に置き換えました。これにより、テクスチャクラスオブジェクトが不要になった際にGC対象になりやすくなります。

FinalizationRegistryによる自動破棄は吉と出るか凶と出るか

しかしChatGPTに聞いてみたところ、このFinalizationRegistryによるリソースの自動破棄と弱参照によるGCコントロールは、Three.jsやBabylon.jsなどのメジャーなライブラリでは利用されていないようです。GC処理に起因するフレームドロップを避けたい狙いがあるのでしょう。
あとBabylon.jsの場合、リファレンスカウント方式による特別な管理をしているとGPTが言っていますが、本当なんでしょうか。ちょっと気になりますね。

image.png

しかし、群衆シミュレーションのような大量のオブジェクトを生成・破棄するようなケースでは、フレームドロップを許容してでもGCによる使用メモリのリダクションコントロールが必要になるケースがあるかもしれません。

image.png

Rhodoniteでは後者のケースも想定してFinalizationRegistryと弱参照による自動解放機構を作ってみました。まぁ、どちらというとそこに釘があったからとりあえず打ちたくなったともいうんですが(爆

Khronos Fidelity Comparisonへの適応

Khronos Fidelity Comparisonという、各種レンダリングライブラリのglTF描画結果を比較するサイトがあります。このサイトが使っている仕組みにRhodoniteを適合させ、three.jsやBabylon.jsなどと同じ条件で描画結果を比較できるようにしました。

image.png

これの利点は、数々の著名なレンダリングライブラリと同じ条件(描画に使う3Dモデル、IBLに使うHDRI、カメラアングル)で描画結果を比較できることです。ライブラリを自作している方はぜひ、自分のライブラリの描画品質のチェックに利用されてみてはいかがでしょうか。

TypeScriptの循環参照(import循環参照)の解消

昨年までのRhodoniteは、多くのTypeScriptファイルの間でimportの循環参照が起きてしまっていました。だいぶリファクタリングをして、これらの全てを解消しました。

Loggerクラス導入

コンソール出力のほとんどをLoggerクラスを通して行うようにし、設定したログレベル未満のレベルのログは出力しないようにしました。

さいごに

ここ数年、モチベの波が激しく、ひどい時は「CGなんも興味無くなった\(^o^)/」「Rhodoniteもう更新することはないだろうな……」みたいな境地になることまであったのですが、そのうちするとまた戻って来れるので、なんだかんだで私はCG好きなのかもしれません。

ただ、Rhodoniteの将来をどこへ向かわせるか、という部分は少し迷っています。それが定まるまでは、気ままに機能増強を続けるかもしれません。

みんなも自作ライブラリ作ってみようず(´・∀・`)

ということで、みなさま良いクリスマスを!

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?