この記事はGoodpatch Advent Calendar 2022 14日目の記事です。
Strapチーム フロントエンドエンジニアの古家です。
Goodpatchが提供するオンラインホワイトボード『Strap』ではホワイトボード部分の描画にPixiJSを利用しています。
PixiJSはウェブブラウザのcanvas要素に描画する、クロスブラウザ対応の軽量なJavaScriptライブラリ。
JavaScript から GPUを扱うWebGL技術を2Dに特化して平易に利用できる。
WebGL未対応の環境では従来のCanvas描画方式に切り替えて描画され、プラットフォームの差異を吸収する。
今回は年末らしく、StrapエンジニアチームがPixiJSを利用していて遭遇した問題について振り返ってみようと思います。
StrapチームとPixiJS
WebGLとCanvasの描画差異
- Hole in masks are not rendered with CanvasRenderer · Issue #7509 · pixijs/pixijs · GitHub
- Canvas's TilingSprite should be rendered independent of Texture resolution · Issue #8055 · pixijs/pixijs · GitHub
- Bezier curve issue with line alignment in Canvas · Issue #8056 · pixijs/pixijs · GitHub
- Mask might not be applied correctly when using Extract · Issue #8105 · pixijs/pixijs · GitHub
- TilingSprite's tileScale is not applied correctly in CanvasRenderer · Issue #8386 · pixijs/pixijs · GitHub
- Fix a problem of line alignment on CanvasRenderer by ymegane · Pull Request #8053 · pixijs/pixijs · GitHub
これらはStrapチームが報告したissueたちです。 中には私の方で修正PullRequestを出して無事マージされたこともありました。(嬉しかったです)
さて、これらのissueのタイトルに注目すると、Canvasでの描画に関連した問題が多いことがお分かりいただけると思います。
先ほどのWikipediaの紹介のように、PixiJSはWebGLでの利用を中心としたフレームワークですが、WebGL(GPU)が利用できない環境でのフォールバックとしてCanvasを利用した描画もサポートしています。
一見シームレスにどちらの環境に対しても対応できる機構ですが、内部実装としてはWebGLRendererとCanvasRendererの2つのRendererが実装されています。 それぞれのRendererは独自に描画処理を実装しているため、しばしば動作に差異が生まれてしまいます。
どうやらStrapはPixiJSユーザーの中でもCanvasRendererを使い倒しているプロダクトにあたるようで、未発行の不具合に遭遇することも多いようです。
Canvasモードのサポートが重要な理由
もしかすると、この記事を読むような方にとっては、今どきWebGL(GPU)が使えない環境なんてあるの?GPUくらい使える環境が当たり前なのでは?と思われる方も多いのではないでしょうか。(かつて私もそうでした)
例えば、GPUが利用できない状況としては、VDI(仮想デスクトップ環境)からご利用いただいている場合があります。 サービスのオプションとしてGPUが提供される場合もありますが、大抵の場合は追加料金となります。 Strap導入のために検討いただくことは難しいことが多いです。
また、ブラウザによってはWebGL描画に問題のある特定のGPUドライバをブロックする機構が存在しています。 ハードウェア的にGPUを搭載していても、WebGLが利用できないケースがあります。 参考: BlacklistsAndWhitelists - WebGL Public Wiki
Strapは、すべてのチームが使えるオンラインホワイトボードを目指しています。 このようなプロダクトのコンセプトから、さまざまなPC環境の方に導入いただけることを重要視しています。
StrapではCanvasRendererを利用した描画モードを、互換表示モードとして提供しています。
CanvasRenderer廃止の危機
実装差異のメンテナンスコストや実装の簡素化を目的に、現行バージョンであるPixiJS v7のプロポーザル時点では、CanvasRendererの廃止も検討されていました。 最終的には有用性が再評価され残されることになりました。
Modernize PixiJS in v7 · Discussion #7541 · pixijs/pixijs · GitHub
将来にわたってCanvasRendererのサポートが継続するかは不透明ですが、Strapにとっては一安心といったところでした。
現在のCanvasRendererはWebGLRendererと一部のコードを共用していますが、よりシンプルにCanvas描画を提供できるよう、独立したバンドル化なども検討されているようです。こちらも実現性は不透明です。
Proposal to Create Canvas-only bundle · Discussion #8477 · pixijs/pixijs · GitHub
個人的なPixiJSとの付き合い方
Strapはそのプロダクトの性質上、プロダクトにおけるPixiJSの重要度はかなり大きいものになります。 継続した機能追加や安定したサービスを提供する上で、定期的なパッケージの更新や、メジャーバージョンアップへの追従は重要な活動になります。
日々リリースされる新バージョンでの差分や、次期メジャーバージョンのロードマップのキャッチアップも重要です。
これらのキャッチアップを効率よく行うため、個人的にやっていることをご紹介します。
Repositoryを日々ウォッチ
Gitクライアントで開きっぱなしにしておくと日々の差分が流れてきます。
リリースがあれば新規のタグ発行で気づくことができますし、日々マージされたPull Requestの差分もすぐに確認することができます。
変更の背景など、コードだけで理解できないことも多いため、よくわからない時はPull Requestを覗きに行くこともあります。
コミュニティを眺める
このほかにも、GitHubのDiscussionsやDiscordなどのコミュニティも存在しており、ゆるーく眺めるなどしています。
定期的にAMAが開かれたり、次期バージョンのディスカッションが行われるなど、今後の方針をキャッチアップしておくのに便利です。
最後に
Strapチーム(と私)とPixiJSの付き合い方についてご紹介しました。 PixiJSとの付き合い方について、少しでも雰囲気が伝われば幸いです。
また、私たちが起票したissueのなかには未解決のものもあります。 この記事を読んで、もしPixiJSに興味を持たれた場合は、ぜひ修正にチャレンジしてみてください🥹
それでは、明日のAdvent Calendarもお楽しみに!