突撃!隣のリモートワーク環境 2021

この記事は Tech KAYAC Advent Calendar 2021 の23日目の記事です。

技術部2年目サーバサイドエンジニアのkolukuです。
2年経っても未だにコロナ下にある昨今、去年から引き続きリモートワークを行っている会社も多いのではないでしょうか?自分自身も入社直後からリモートワークで人と接点が無く、時々他の社員はどんなふうに仕事をしているのか思いふけることがあります。

リモートワークといえば、昨年はリモートワークでこう仕事しています!という紹介記事がたくさんありました。それを思い出した自分は社内で「2年かけて熟成されたリモートワーク環境のデスクを見てみたいので、なるべくありのままの状態を見てみたい」という要望で募集したところ、なんと14名も本企画に参加いただけました!

エンジニア編

エンジニアのデスクと聞くと「とにかくモニターがいっぱいに並んでいそう」「ガジェットでごちゃごちゃしていそう」などそんなイメージを一度は持ったことはないでしょうか。リモートワークは職場とは違い、各々の自宅で作業されるため個性豊かな環境で仕事をしていそうなものですが、実際にどのように働いているのか見せてもらいました。

ゲーム事業部/サーバーサイドエンジニア/koluku

f:id:koluku:20211222161420j:plain

トップバッターは本企画の言い出しっぺ、筆者です! 本企画で唯一のスタンディングデスク導入しており、自然あふれるスタイルになっています。

気に入っているところ・こだわりポイント

オンラインミーティングだと音質が悪いと相手に悪いので1万円のマイクを奮発して買いました。特に声がか細いのでなるべく集音性が良いコンデンサーマイクで音を拾ってゲインとノイズキャンセリングを噛ませてミーティングに挑んでいます。

机は以前はBauhutteの横幅120cmデスクを使っていたのですが、ゲームと仕事で公私を分けたいと思って新たにスタンディングデスクを導入しました。天板を自分で用意しないといけなかったので暗めの色の硬い木材で、とにかく幅広くしたかったのでKANADEMONOで買った天板を選びました。めちゃくちゃテンションがあります。

こういうのがあったら便利・欲しいと思った物

ある程度立ちながら仕事するとだんだん足が辛くなるのですが、緩衝マットを入れると椅子を入れづらくなって相性が悪いのでリカバリーサンダルみたいなスリッパに近い形のものを導入が良さそうです。

ゲーム事業部/クライアントエンジニア/@p_chin

f:id:koluku:20211222161430j:plain

お子様の笑顔が眩しいデスクトップです。大量のガムに目が行く一方で、個人的には商品の化粧箱を台にしてモニターを設置する工夫が見えるのがおちゃめポイントだと思いました。

気に入っているところ・こだわりポイント

座高が高い影響でなかなか良い高さの机がなかったので、ニトリで買った昇降式の机を使ってるところですね。
あとは今までMacBookのキーボードを使ってたのですが、夏の在宅勤務でPCの熱が熱くて手汗やばかったので外付けのキーボード買いました。今は冬なので、逆に寒くなっちゃって...手から離れてしまったPC熱が恋しいですね(笑
あとはボトルガムです。歯も健康になるし、仕事しながら顎を鍛えられる気がして便利だと思います。
最後に、今はPCのデスクトップ背景を息子にしてるのですが目に入ると癒されて捗ります。

こういうのがあったら便利・欲しいと思った物

パジャマでベットに寝てる時が一番リラックスできて捗るので、寝ながらPCのキーボードやマウスをシミュレーションしてくれる何かがあると嬉しいです。

ゲーム事業部/Unityエンジニア/oga

f:id:koluku:20211222161443j:plain

Macbookを含めるとなんと本企画の中で最大の5画面!その中でも中央はワイドモニターです。モニターを2つ並べると中央にモニターのベゼルが来てしまうので、それを解決できるワイドモニターは筆者も注目の道具です。

気に入っているところ・こだわりポイント

リモート2年間の末出来上がった汚デスクです。
リモート前はモニタ3枚だったのですが仕事用のmacを繋げるついでに増やしたら4枚になりました。
左のモニタはゲーム機にも繋がってるので仕事が終わったらシームレスにゲームが遊べます。

こういうのがあったら便利・欲しいと思った物

仕事用のmacが一枚しかモニタに繋げてないので他のモニタにも繋げるようにしたいです。 定期的にゴミ出ししてくれる人が欲しいです。

ゲーム事業部/にーの

f:id:koluku:20211222161406j:plain f:id:koluku:20211222161355j:plain

シンプルとおしゃれさを保ちつつゲームへのアクセスが良い機能性を備えており、綺麗を超えて完璧ではと思わせてくれるデスクです。間接照明を入れると程よい光をいれつつおしゃれな雰囲気を出すことができるのでおすすめです。

気に入っているところ・こだわりポイント

リモートワークというよりもゲームに比重を置いたデスクです。全体的に好きなものに囲まれて目の保養をしつつ、各アイテムへアクセスしやすくてスッキリと見えるようなデスクを目指してます。
こだわりポイント3つ↓

  • 配線系を左側の1箇所に流れをまとめつつ、ブックスタンドを使ってに入らないように隠しているところ
  • コントローラーを3つ置けるスタンドの1番上のフックを逆さまにして高さを出してヘッドホンを掛けられるようにしたところ
  • USBポートやキャプチャーボードなどの位置がずれやすいものは裏に両面テープを貼って固定してるところ

気に入っているところ↓

  • 気分によって右上のピクセルアートを差し替えてテンション上げられるところ
  • ゾイドかっこいい

こういうのがあったら便利・欲しいと思った物

机が大きくないので今はシングルディスプレイですが、できればデュアルディスプレイにしてみたいです。

ゲーム事業部/サーバーサイドエンジニア/commojun

f:id:koluku:20211222161454j:plain

CPUとメモリはよく作業者と机の関係で説明されますが、紙を使う作業はとにかく場所を取るので実際に机を広げることで能率を上げているみたいです。電子機器を増やすたびにケーブルコントロールに苦しむのはもはや世界共通の様式美です。

気に入っているところ・こだわりポイント

作業スペースはとにかくたくさんあったほうが良いと思って事務用の長机を使っています。頻繁に手書きでメモをするので、キーボードの手前にB5ノートを広げられるスペースを必ず確保しています。昔デュアルディスプレイをしていたとき首が痛くなったので、基本的に右のディスプレイしか使いません。右の本棚にもよく使う文房具やPC周辺機器を収納できるスペースを確保しています。
PCのスペックが不足気味なので、オンラインミーティングの通話はiPadでやるようにしています。

こういうのがあったら便利・欲しいと思った物

何か機材を追加する度、ケーブルのとりまとめが大変です。

クライアントワーク事業部/フロントエンドエンジニア/miyabin

f:id:koluku:20211222161425j:plain

なんとMacとWindowsの両刀遣いです。2台もあればデバイススイッチングが大変なのでは?と聞いたところ、そのために両方のマウス(トラックパッド)とキーボードを並べていますとお答えいただけました。それもそうですね!

気に入っているところ・こだわりポイント

仕事用のmacと自宅用のwindows、どちらもデュアルディスプレイで使えるようにしてあるところ

こういうのがあったら便利・欲しいと思った物

椅子の下に弾くマットがボロボロなのでいいものがあったら買い換えたい

人事部/エンジニア/tamiflu

f:id:koluku:20211222161433j:plain

本企画の最初のエントリー者です。本当にありがとうございます。この方のようにサブモニターを縦にするとターミナルのログやSlack、Twitterを長いタイムラインで垂れ流すことができて便利なのでモニターを増やしたいけど使い方に悩むという方におすすめです。

気に入っているところ・こだわりポイント

なるべく手元のスペースが開くようにiMac以外のモニタはアームにぶら下げてます。真ん中のモニタはHDMIセレクタで仕事用のMacbook、iMac、Nintendo Switchを切り替えられるようになっている

こういうのがあったら便利・欲しいと思った物

いっそのことウルトラワイドモニタを置くと全体的にすっきりするのではと思ってます。配線が難しい

CorporateITチーム/やましん

f:id:koluku:20211222161450j:plain

作業場所が狭くなることで失われてしまう物の置き場所を壁に移すことでその問題をクリアしているようです。ワイヤーネットやフックは100円ショップでも買えるのでコスパのいい対策です。

気に入っているところ・こだわりポイント

  • 部屋の隅っこ0.5畳に構える唯一のマイスペースです
  • 狭いスペースを生かして壁面にワイヤーネットを設置することで必要なものが置けて散らかりにくいです
  • 仕事に集中できるよう、余計なものは極力置かないようにしています
  • 椅子はしっかりしたものにしたかったのでアーロンチェアを使用しています

こういうのがあったら便利・欲しいと思った物

  • スペースが限られているのでマイクアームなどが増設しにくい
  • 薄型ディスプレイにしたらWebカメラの設置場所がなくなってしまった

というのが最近の悩みです。

備考欄

「見栄を張りましたがアーロンチェアは会社からの借り物です!!!!!!!」

ゲームコミュニティ事業部/macopy

f:id:koluku:20211222161415j:plain

この方は社内でも随一の自作キーボードを作ることで有名です。よく見るとデスクの右端にはんだごてが写っているのですぐに作業に取りかかれるようになっているので、自作キーボードへの隠しきれぬ熱意を感じます。

気に入っているところ・こだわりポイント

ここ1年はキーボードにkeyboardio atreusを使っていたのですが、リモートワークの日と出社の日が最近は半分ずつになったため、atreusっぽいキーボードを自分で作ってみました。
キーボードの高さはスライド式のキーボードトレイで調節しています。

こういうのがあったら便利・欲しいと思った物

「昔使っていたキーボード」が増えていくので、コレクション用の棚が欲しいなと思っています。今日はこのキーボード、みたいな感じで気分で変えられる生活を送りたい。

匿名希望

f:id:koluku:20211222161410j:plain

なんと40インチ超えのモニターをドン!目の前です!27インチを超えるだけでも迫力があるのに43インチはもはや未知の領域です。筆者も一度気になって家電量販店で見に行った際には「えっテレビ…?えっ普通にウィンドウ開いても残り3隅だだあまりじゃん…」と困惑するほどです。それだけに使いこなせるのはすごいです。

気に入っているところ・こだわりポイント

  • ディスプレイは勢いで買った43インチの4Kです。ウィンドウをBetterTouchToolで分割配置しつつマルチディスプレイ感覚で使っています。
  • キーボードはREALFORCE SA for Macです。打鍵の軽さがお気に入りです。
  • スタンドに載せたAndroidタブレットには、24時間365日でGoogleカレンダーを表示しています。これを導入してから予定を忘れることが大幅に減りました。

こういうのがあったら便利・欲しいと思った物

  • 43インチ、13kgを支えられるモニターアーム
  • 仕事とプライベートの空間を分ける、2つ目の部屋

匿名希望

f:id:koluku:20211222161517j:plain

自分のデスク、と見せかけて実はお子さんの机です。
子供が多い家庭は親の居場所を奪われがちで、作業中でも子供が来たら対応しないといけなくなります。筆者が参加するミーティングでは子供が部屋に突撃してしまい、ミュートになる光景がしばしば見られます。

気に入っているところ・こだわりポイント

地図のデスクマット。子供の机を間借りしているので、下校後は場所がなくなります。

こういうのがあったら便利・欲しいと思った物

お部屋がもう一つ欲しいです

非エンジニア編

本企画は当初Tech blogに属する内容のためエンジニアが所属するチャンネルで募集をかけたのですが、弊社に所属する社員はなにもエンジニアだけではないので途中からエンジニア以外の方にも質問してみたところ、3名からお答えいただけました!

ゲーム事業部/たいが

f:id:koluku:20211222163752j:plain f:id:koluku:20211223095707j:plain

本人からの備考によると実は1枚目の写真に写っている机は奥様が使っていて、本人は2枚目の写真の地べたに座ってちゃぶ台で作業しているとのことです。せ、世知辛い…。

気に入っているところ・こだわりポイント

3人いるので大丈夫ですねヨシ!

こういうのがあったら便利・欲しいと思った物

ゲーミングチェアとPCデスクもう一つずつ欲しいですね

企画部/飯村智也

f:id:koluku:20211222162606j:plain

Simple is Best。パソコンさえあればどこでも働けるというノマドワーカーのような粋を感じます。本人も語っていますが、4:3のモニターは今どきすごく珍しいので筆者はこの写真を見たときに小学校のパソコンルームが脳裏をよぎりました。

気に入っているところ・こだわりポイント

モニターが4:3!
わざわざ探した。

こういうのがあったら便利・欲しいと思った物

モニターをちょっと高めの位置に置きたい(週刊少年ジャンプを噛ませればいいのかもしれない)

ゲームコミュニティ事業部/きゃんてぃ

f:id:koluku:20211222161359j:plain f:id:koluku:20211222161439j:plain

文鳥がかわいいですね!ペットが寂しがり屋で目の届く位置に置いているというのはよく聞くので場所に困りそうですが、この方はモニターと同じ台に置くことで場所を確保しているみたいです。

気に入っているところ・こだわりポイント

ペットの文鳥が寂しがるのでデスクのすぐ横に配置しています、仕事中はずっと凝視されています。机は10年位使っている無印良品のパイン材テーブル、奥行きが狭いので買い替えたいです。

こういうのがあったら便利・欲しいと思った物

3000円の椅子を使っていますが腰が痛くなりやすいので、やはりアーロンチェアは偉大。

終わりに

最後に外部モニターの導入数とMacbookのクラムシェルモードの使用割合が気になったことがあったので数をまとめてみました。

外部モニターの数 人数(割合)
0枚 1名(7%)
1枚 9名(65%)
2枚 2名(14%)
3枚 1名(7%)
4枚 1名(7%)

モニターの大きさも影響はありますが、台数は場所の確保と操作感が1台増えるごとに大きく違うので見てみましたが、やはり1台での運用の方が多いみたいです。

Macbookをどう使っているか 人数(割合)
クラムシェルモード 6名(50%)
開放 6名(50%)

クラムシェルモードについては排熱のための表面積が小さくなるためCPU性能に影響が出る場合があり、それでも利便性で畳んで使用しているのかが気になりました。見てみると半々に分かれて面白い結果になりました。


他にも個性あふれるデスクがあったのですが、様々な理由から自主規制でお蔵入りとなってしまい見せることができずに残念です。 仕事だけに最適化しました!という机だけではないというのが弊社のエンジニアらしさがあるのではないでしょうか。

以上のリモートワーク環境がみなさまのデスク整備の参考になればと思います。

明日24日のクリスマスイブはobaraさんです!

WebGL2でCPUベースのレイトレーシングをやってみた

この記事はKAYAC Advent Calendar 2021の22日目の記事になります。

こんにちは!ハイカジチームの深澤と申します。

今回は実際の業務とは関係なく、自由研究的にやってみたことの記事になります。

数ヶ月ほど前に iOS15, macOS Monterey が登場し、ついに iOS / macOS ともに safari で WebGL2 が標準で使えるようになりました。この出来事はWebフロント界隈からするととても嬉しいお知らせでした。

そのことを思い出し、アドベントカレンダーでは WebGL2を使った何かを題材にしようと決め、前々からやってみたかった「ブラウザでCPUベースでレイトレをし3Dモデルを表示する」ことに取り組んでみたという経緯になります。

ここでいう「CPUベース」とは、「レイトレのピクセル計算をjavarcript側で行うこと」を指します。

目次

はじめに

今回の記事では、 ブラウザでCPUベースのレイトレを実装するにあたってどういう仕組みにしたか を中心に書いていきます。

なので、レイトレそのもの・コードベースでのレイトレについての記載は少なめになることをあらかじめご了承いただけますと幸いです。

また、ブラウザでのレイトレ自体はWebGL2であることが必須ではなく、結局本文でもWebGL2に関しての記述は少なくなりました。

自分が書いたレイトレ関連のプログラムは主に Ray Tracing in One Weekend — The Book Series を参考にさせていただきました。

できたもの

こちらになります。真ん中の宝石のような形のオブジェクトがOBJのデータになります。

f:id:takumifukasawa:20211221020914p:plain

今回「htmlファイル1つに全て書く」こともサブ目標にしていたので、アセットはhtml一個のみです。OBJのデータもテキストで埋め込みました。

また、ブラウザで行うのでインタラクションで絵が変わるようにしたいなと思い、Canvas上のマウス位置に応じてカメラ座標が変わり絵が更新されます。

f:id:takumifukasawa:20211221002757g:plain

綺麗な絵を出すこともやってみたかったので、初期サンプリング数ですべてのピクセルを描画し終わったらサンプリング数をさらに増やして各ピクセルを描画し直す流れを繰り返し、放っておいたら徐々に綺麗な絵に近づくようにしています。


動作デモとリポジトリはこちらになります。

動作デモ

https://takumifukasawa.github.io/js-raytracing-sandbox/for-article.html

リポジトリ

github.com

絵を出すアプローチ

グラフィクスAPI

まずレイトレーシングの前に、グラフィクスAPIを使ってなにかを表示する方法を振り返ってみます。グラフィクスAPIでは一般的にはラスタライズ法を用いてモノを表示させていきます。大雑把には以下のような流れになります。

頂点がどこの位置にあるかのデータを用意
↓
グラフィクスAPI経由でGPUに送る
↓
どういう形(点・線・面)で描画するかを設定
↓
頂点シェーダーを経由してスクリーン上のピクセル位置を決定する
↓
ピクセルシェーダーで色を決定

これを繰り返していくことで画面に絵が出力されるわけですね。

(イメージ図)

f:id:takumifukasawa:20211220223957p:plain

レイトレーシング

対してレイトレーシングは、レイという概念を使って色を計算していきます。レイは「どこから」「どこに向かって」という2つの情報を持っています。流れはざっくり以下のようになります。

視点から各ピクセルを通してシーン(どこに何があるかを管理するもの)に向かってレイを飛ばす
↓
何かに当たったら反射した先を探す
↓
また何かに当たったら反射した先を探す
↓
... 繰り返し ...
↓
どこかで追跡をやめ、反射情報を元に色を決定

(イメージ図)

f:id:takumifukasawa:20211220224632p:plain

疑似コードは例えばこのようになります。ループが続き、なんとなく計算量がとても多くなりそうですね。

for(let i = 0; i < height; i++) {
  for(let j = 0; j < width; j++) {
    // 各ピクセルの処理
    ...
    // ピクセルごとにサンプルする数。スーパーサンプリング
    for(let k = 0; k < sampleCount; k++) {
      // 最大追跡回数
      for(let l = 0; l < maxIterationCount; l++) {
        // rayを追跡
      }
    }
  }
}

あらためて、レイトレーシングはざっくりまとめると各ピクセルごとにレイを追跡して反射を繰り返す計算方法になります。現実の光で発生するような反射の繰り返しのシミュレーションに近くなるので、光の当たり方などがより自然になりやすいです。パストレーシングと呼ばれる手法ではもっと自然な見た目に近づいていきます。

この方法はグラフィクスAPIを使わなくても実現が可能です。今回はWebGL2を使いましたが、Canvasのcontext2dでも同じことができます。

擬似コードで簡単に触れたように、レイトレーシングで問題になるのは「計算時間」です。綺麗な絵を求めれば求めるほど反射の追跡回数やエイリアスの削減などで計算回数が膨大になります。

実際に作ったレイトレーサーの構成

もしシェーダーだけでレイトレをする場合、板ポリを1枚用意しシェーダーで各ピクセルごとにレイトレをする方法が考えられます。いわゆるレイマーチングによるシェーダー芸はこのやり方ですね。今回は各ピクセルの計算はjavascript側で行い、描画機能はWebGLに担当してもらいます。

オフスクリーンレンダリングで計算結果を溜めていく

javascript側で色の計算をしたのちに、何らかの方法を使ってWebGL経由でデータを渡し描画する必要があります。そこで、計算結果をオフスクリーンレンダリングでテクスチャに描画していき、そのテクスチャを画面に表示する流れをとります。

オフスクリーンレンダリングでは、FramebufferとTextureを用意します。Three.js,UE4では RenderTarget、Unityでは RenderTexture にあたるものですね。今回はThree.jsに寄せてオフスクリーンレンダリングの描画先のことを RenderTarget と呼ぼうと思います。

1. 一回で同時に計算するピクセル数分、座標と色情報を持つ頂点を生成
2. 同時に計算するピクセル数分、更新するピクセルを選択し、色を計算
3. 選択したピクセルの位置をクリッピング座標に変換し、1で生成した頂点の座標と色情報を更新。
4. RenderTargetに描画。この時、clearはしないことでピクセルの色を上塗りしていく
5. 同時に計算するピクセルの数、次に更新が必要なピクセルを選択
6. ... ピクセルの選択と描画を繰り返す

以下、同時に8ピクセルを更新していく場合を図にしてみました。zは必ず0にしているので、xyだけをWebGL経由で渡す形でもよかったと思います。

f:id:takumifukasawa:20211221104631p:plain

こうして、ピクセルの色が蓄積されていきます。

f:id:takumifukasawa:20211221002957g:plain

図の中にあるように、頂点情報の管理はVertexArrayObject(VAO)を使いました。WebGL2からの標準機能で、頂点バッファやインデックスバッファをまとめて管理してくれる便利な機能です。今回はWebGL2ベースなのでVAOを使ってみました。

developer.mozilla.org

計算したピクセルを表す頂点を描画するためのシェーダーは、渡された頂点位置と色をそのまま出力するだけなのでとてもシンプルです。

頂点シェーダー

#version 300 es
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aColor;
out vec3 vColor;
void main() {
  vColor = aColor;
  gl_Position = vec4(aPosition, 1);
  gl_PointSize = 1.0;
}

ピクセルシェーダー

#version 300 es
precision mediump float;
in vec3 vColor;
out vec4 outColor;
void main() {
  outColor = vec4(vColor, 1);
}

画面に表示する

これで計算結果をRenderTargetに格納していくことができました。しかし、オフスクリーンレンダリングをしているのでまだ画面には何も映っていません。ただ、あとはRenderTargetを画面に表示させるだけでよいのでこちらもシンプルです。

canvasサイズ全面に広がる板ポリを用意し、uniformでRenderTargetのテクスチャを渡し、そのテクスチャを表示するシェーダーを書くという流れになります。

ピクセルの色計算を WebWorker に逃がす

レイトレーシングで大きな問題になってくる「計算量」ですが、ブラウザでの実行、それもなるべくリアルタイムなインタラクションつきでとなると多少絵が汚くなってもよいので、操作に影響が出にくいような構成が望ましいです。

WebWorkerの使用

ブラウザでのjavascript実行は基本的に単一スレッド(メインスレッド)なので、重い計算をCPUで行えば行うほどメインスレッドが詰まりブロッキングが発生し、UI 要素の反応が非常に悪くなっていきます。

そのため、レイトレの色計算部分をWebWorker に投げる ことにします。具体的には以下のような流れになります。

1. レイトレに必要な情報(更新するピクセルの数など)をWebWorker.postMessageで投げる
2. WebWorkerで計算
3. 更新する頂点座標・色情報群をWebWorker.onmessageで受け取る
4. RenderTargetに描画
5. 1に戻る

developer.mozilla.org

webworker関連の流れを一部抜粋してみます。実装上ではworkerを複数生成しています。

  ...

  // workerに投げる
  const tryExecWorker = async (i) => {
    ...
    /*
     * args: workerに送るデータ
     * {
     *   scene, // シーン情報
     *   camera, // カメラ情報
     *   width, // 横幅
     *   height,  // 縦幅
     *   sampleCountPerPixel, // ピクセルごとにスーパーサンプリングする数
     *   maxRayIterationCount, // 最大追跡数
     *   updatePixelIndexes // 更新するピクセルのインデックス群の配列
     * };
     */
    this.#workers[i].worker.postMessage([args]);
    ...
  }

  // workerから受け取る
  worker.onmessage = async (e) => {
    const [args] = e.data;          
    // RenderTargetの更新
    this.updatePixels(args);
    tryExecWorker(i)
  };

  updatePixels({ positions, colors }) {
    // 頂点ごとのデータが配列の入れ子になっているのでflatをかける
    // updateAttribute内ではbufferSubDataでデータを更新している
    this.#pointGeometry.updateAttribute('position', positions.flat());
    this.#pointGeometry.updateAttribute('color', colors.flat());
    this.updateRenderTarget();
    ...
  }
...

// workerのスクリプト
self.onmessage = (e) => {
  const [args] = e.data;
  // calcPixelsColorは色計算をするメソッド
  const result = RaytraceRenderer.calcPixelsColor(args);
  postMessage([result]);
}

WebWorkerに渡すデータ構造の注意

レイトレとは少し話がずれます。

メインスレッドで重い計算をすることで発生しうる問題の回避につながるWebWorkerですが、使用に際し注意点・ハマりどころがあります。

それは、渡すことのできるデータと渡せないデータがあることです。例えばWebWorkerに関数を渡すことができまん。

以下はMDNからWebWorkerに渡されるデータについての注釈の抜粋です。

メインページとワーカーの間で渡されるデータは、共有ではなくコピーされます。オブジェクトは、ワーカーに渡されるときにシリアライズされ、その後、反対側でシリアライズが解除されます。ページとワーカーは同じインスタンスを共有しないため、最終的には両側に複製が作成されます。ほとんどのブラウザーはこの機能を構造化複製として実装しています。

Functionオブジェクトがこの例で、インスタンスしたクラスをpostMessageで渡してもメソッドは渡されません(インスタンス自体がObjectに変換される)。

developer.mozilla.org

developer.mozilla.org

chromeで下記を実行すると Object で { hoge: "hogehoge" } が出力されます。クラスのインスタンスではなくなっていることが分かります。プライベートフィールドも関数同様コピー対象にはなっていないようですね。

class Hoge {
  hoge;
  #fuga;
  constructor(hoge, fuga) {
    this.hoge = hoge;
    this.#fuga = fuga;
  }
  echo() {
    console.log(this.hoge);
    console.log(this.#fuga);
  }
}

const hoge = new Hoge("hogehoge", "fugafuga");

const worker = new Worker(URL.createObjectURL(new Blob([`
self.onmessage = (e) => {
  console.log(e.data[0]); // Object { hoge: "hogehoge" }
}
`])));

worker.postMessage([hoge]);

このように、渡すデータ構造には注意が必要なのでそれを踏まえた設計をしてあげる必要があります。今回自分はクラスのプライベートフィールドを多用した結果この問題に引っかかり、関連部分は全部パブリックにしました。

今後

BVHやkd-treeによる探索の最適化は今回入れていないので次にやってみたいことです。BVHは途中まで実装してみていたのですがメッシュ分割を踏まえたBVHのやり方がいまいち分からず、今回は取りやめました。

また、パストレーシングをブラウザでやってみたら負荷がどうなるかが気になっています。計算負荷的にインタラクション連動はあまり望めないかもしれませんが、時間がかかってもブラウザでパストレの絵が出せたらとても楽しそうですね。

参考

こちらにまとめさせていただきました。

github.com

最後に

レイトレ楽しかったです!ここまで読んでいただきありがとうございました!

明日は koluku さんの記事です!