Slide 1

Slide 1 text

TypeScript(WebGL)+React+Vite で、 さくっと Geodesic Polyhedron を描画してみた フォルシア株式会社 旅行プラットフォーム第6部 
 辻 裕太
 2022/11/14 Shinjuku.ts #1


Slide 2

Slide 2 text

2 自己紹介
 ● きみだれ
 ○ tsuji と申します
 ○ 今年 フォルシア新卒入社🐤
 
 ● 好きな言語
 ○ TypeScript
 ■ 特徴:JavaScript に gradual typing を適用した言語 
 ■ 個人開発・バイトで使用 
 ■ 開発業務でも
 ○ Rust
 ■ 特徴:静的型付け、多相、所有権、ライフタイム、高い実行速度など 
 ■ 個人開発・研究で使用 
 ● 手続きマクロでDSLを作るなど 
 ■ 2年前、弊社インターン(Rustインメモリデータベースコース)に参加 


Slide 3

Slide 3 text

本題
 3 とある週末、ダラダラしながらこんなことを考えていました
 「頂点がおおよそ均等に分布する球って、
              どうやって構成するんだろう...?」
 - 地球のような、緯線・経線に沿った頂点の配置は直感的
 - 極に近いほど面のサイズが小さくなる(=頂点の密度が上がる) 
 
 
 
 密
 疎


Slide 4

Slide 4 text

UV Sphere / ICO Sphere
 4 - ggったら、主に2つの手法が見つかった
 
 - UV Sphere
 - 地球みたいな頂点の配置
 - 頂点の分布に偏りがある
 
 - ICO Sphere
 - 多面体から構成される
 - 頂点がおおよそ均等に分布
 - Geodesic Polyhedron が正式名称らしい
 Geodesic polyhedra are available as geometric primitives in the Blender 3D modeling software package, which calls them icospheres: they are an alternative to the UV sphere, having a more regular distribution of vertices than the UV sphere. https://en.wikipedia.org/wiki/Geodesic_polyhedron

Slide 5

Slide 5 text

Geodesic Polyhedron の構成方法
 5 1. 多面体を用意します
 2. 各面を複数の三角形に分割します
 3. 分割によって得られた各面内の頂点を球面上に押し出します
 4. できあがり
 
 
 
 
 今回は、これを正二十面体で実装した(見た目が良かった)
 https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Ge odesic_icosahedral_polyhedron_example.png/2880px-Geodes ic_icosahedral_polyhedron_example.png

Slide 6

Slide 6 text

デモ
 6 https://forcia-tsuji.github.io/geodesic-polyhedron/


Slide 7

Slide 7 text

やったこと
 7 ● 目的
 ○ Geodesic Polyhedron を描画する 
 ○ できたものを公開したい
 ○ (描画に使う OpenGL 系ライブラリの API の復習もしたい) 
 
 ● やったこと
 ○ Vite でスッと開発環境を構築し、
 ○ React で雑にcanvas elementとボタンを生やし、 
 ○ WebGL でいい感じに Geodesic Polyhedron を描画 
 
 


Slide 8

Slide 8 text

Vite:開発環境構築
 8 - 開発環境をささっと構築できるツール
 - 今回やりたいことに適していた
 - hot reload のサポート
 - 文字列の import が可能
 - import VertexShader from 'path/to/main.vert?raw'; - Deployも手軽
 - npm run build 後、生成された /dist ディレクトリを github に push するだけ 
 - 立ち上がりが高速
 
 などなど
 
 コレを付けるだけ


Slide 9

Slide 9 text

React:DOM・イベント操作
 9 - 面の分割数を変更するボタンを作成
 - canvas は再描画させたくないので、分割数の情報は Ref で持つ 
 - canvas element の Ref から WebGL2RenderingContext を生成
 - マウスホイールで分割数の変更ができる
 - React ならイベントの登録が楽
 - addEventListener/removeEventListener とかしなくてもいい 
 - React の強みはそこじゃない 
 
 Q. React 要素少なくない?
 A. ごめんなさい...


Slide 10

Slide 10 text

Geodesic Polyhedron の頂点生成
 10 - 頂点情報はCPU側(TypeScript プログラム)で生成
 - WebGL では Geometry Shader が使えないため 
 - 基準となる正二十面体の頂点情報はベタ書き 
 
 - 面の分割は高校数学で
 - 1辺をn分割するとき、内分点の位置ベクトル v は 元の三角形の各頂点の位置ベクトル v1, v2, v3 を用いて
 
 
 
 
 
 で得られる
 - 考えられる [p1, p2, p3] の組み合わせを二重ループで回せばOK 
 
 v1
 v2
 v3


Slide 11

Slide 11 text

11 - ざっくりとした描画処理の流れは以下
 1. 頂点情報やレンダリングに必要なその他の情報を生成 
 2. Shader によって、CPUから渡された情報をGPU上で加工 
 - Vertex Shader  :頂点に紐づいた値(座標など)を操作 
 - Fragment Shader:ポリゴンの色やその他属性をピクセルレベルで制御 
 3. 画面に出力
 
 - VBOの生成
 ○ ポリゴンの頂点情報が格納されたオブジェクト 
 
 - GLSL(OpenGL Shader Language)プログラムを書き、コンパイル
 
 - Uniform 変数を用いてレンダリング
 ○ TypeScript から各 Shader に、毎フレームで異なる値を渡す 
 - 描画面(表面or裏面)のフラグ:透過処理で使用(後述) 
 - 姿勢を示す3x3行列     :Vertex Shader で、ポリゴンの回転に使用 
 - 姿勢を示す3x3行列の逆行列 :Fragment Shader で、光の反射計算に使用 
 WebGL:Geodesic Polyhedron の描画


Slide 12

Slide 12 text

見た目の調整
 12 - Fragment Shader で色や透明度を調節
 - Phong reflection model の Diffuse/Ambient 項のみ実装 
 - 平行光源からの反射、環境光を表現 
 
 - 頂点の座標を用いて彩色
 - 動くとうれしいので回転を施す
 - 経過時間から回転行列を計算 → Uniform 変数として Shader から呼び出し 
 - 見た目をそれっぽくするために透過処理
 - (ポリゴンの裏面のみ描画 + 透明な表面を描画) + alpha blending(色混ぜ) 
 - 片方の面だけを描画する `Culling` という機能を用いる 
 - 裏面の描画では Diffuse 項を強めにかけ、透けてる感を強調 
 - 表面・裏面の識別に Uniform 変数を使用 
 
 ※それっぽく見えるように調整しているだけで、学術的根拠はありません 


Slide 13

Slide 13 text

まとめ
 13 - Vite を使うことで、一瞬でReact+TSによる開発環境とデプロイ環境が出来上 がった
 - React は...まぁ無いよりは全然いい
 - WebGL(Vertex/Fragment Shader) を用いることで、いい感じの
 レンダリングが行えた
 - TypeScript を用いることで、このLTで発表ができた