Three.js を r116 から r159 にアップデートしたこと
最近、Pixy.js で使用している Three.js のバージョンを r116 から最新の r159 までアップデートしたので、それについてまとめておきます.
EffectTextureMakerというエフェクト用のテクスチャを作成するツールを公開しているのですが、ちょくちょく要望が来たり質問されたりしていました. 機能を追加する前に、まずは最新の環境に更新することにしました.EffectTextureMakerでは自作したシェーダライブラリ Pixy.js を使用しているのですが、これは Three.js を使って実装しています.なので、Three.js を最新にアップデートする必要があります.長い間手をつけずにいたのでバージョンが r116 から最新の r159 まで2年間もの期間が空いたことになります.その間に Three.js も色々変わっていました.
Three.js で気になった変更部分
2020年5月に Three.js の r116 がリリースされ、同時に Pixy.js も更新していました.そこで r116 まで遡ってログを見直しました.以下が気になった変更点です.ほとんどが対応する必要がありました.
- ESM への対応 (three.module.js, three.module.min.js)
- ライブラリが /lib から アドオン /jsm に変わった
- インポートマップを使ってライブラリをインポートし、ESM で実装するようになった
- dat.GUI から lil-gui に変更された
- WebGL2 の対応 (GLSL3)
- WebGPURenderer実装された
- Matrix の getInverse() が廃止され、 invert() に変更された
- PlaneBufferGeometry などがなくなり PlaneGeometry というように単純になった
- BufferGeometryUtils にあった computeTangents が BufferGeometry に実装された
- Geometryの頂点が .vertices ではなく BufferAttribute 経由で取得するようになった
- WebGLMultipleRenderTargets (MRT) が実装された
- UBO (Uniform Buffer Objects)対応
- RGBFormat が無くなった
- CommonJS 形式である three.js, three.min.js が deprecated.r160 で削除される予定(コンソールに警告が出力される)
- カラー管理が colorspace になった
ということで、以下対応した内容です.
ESModuleの対応
Pixy.js の一部のコードは ESM 形式になっていたので、他の部分も ESM に書き直しました. また、ES6の class で再実装するようにしました.
Rollupの更新
Pixy.js は Three.js と同様に rollup でまとめています.こちらも ESModule 形式で出力するようにしました.
サンプルの修正
インポートマップを使用し、すべて を ESM に変更.また、JavaScriptファイルを外部に出してメンテナンスしやすいようにしました.
アドオン
アドオンになってインポートするコードは次のようになります.
import WebGL from 'three/addons/capabilities/WebGL.js';
import Stats from 'three/addons/libs/stats.module.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
使用するときに THREE をつけないので微妙に違和感を感じます.
Matrix.invert()
具体的には以下のようなコード:
projectionCamera.matrixWorldInverse.getInverse(projectionCamera.matrixWorld);
これが次のようになります.
projectionCamera.matrixWorldInverse.copy( projectionCamera.matrixWorld ).invert();
これは normalize()
などと同じ書き方になりました.
BufferGeometryUtils.computeTangents()
BufferGeometry に移動したので楽になりました.
const sphereGeometry = new THREE.SphereBufferGeometry(2, 64, 64);
THREE.BufferGeometryUtils.computeTangents(sphere.geometry);
変更後.
const sphereGeometry = new THREE.SphereGeometry( 2, 64, 64 );
sphereGeometry.computeTangents();
WebGLMultipleRenderTargets (MRT)
MRTがThree.jsにも実装されました.Pixy.js のディファードレンダリングの部分で使用しています.
XXXBufferGeometry
単純に Buffer を消せば問題ありませんでした.
RGBFormat
レンダーターゲットの生成時に指定していたのですが、定数から消えていました. 標準で RGBAFormat であり、alpha パラメータで制御するようになったのかもしれません.詳しく調べていないです.
カラー空間
r152 で ColorManagement API が ColorSpace ベースになりました.最初は gammaInput, gammaOutput、次に outputEncoding 、そして今は outputColorSpace になったようです.これについては別のエントリで書こうと思います(まだ調査中).
lil-gui
GUIメニューの表示に dat.GUI が使われていましたが、lil-gui に変更されました. ある程度互換がありますが、完全に互換があるわけではありません.lil-gui に dat.GUI からのマイグレーションガイドがあるので参考になります.
GLSL3
ShaderMaterial の glslVersion
で指定することができます.
shaderMaterial.glslVersion = THREE.GLSL3;
Three.js 側でマクロを使って GLSL3 でコンパイルできるようになっているので、前のバージョンで書かれたシェーダコードでもそのままコンパイルされるようです.
ですが、RawShaderMaterial を使っている場合は自分で対応しなければなりません.
GLSL3 のシェーダコードは先頭に #version 300 es
を入れるのですが、RawShaderMaterialでも自動で入れてくれます.
ここで、fwidth
などを使うために以下のコードを入れる必要があって、RawShaderMaterialを使う場合はこちらでシェーダコードに入れてました.
#extension GL_OES_standard_derivatives : enable
どうもこの辺りの宣言順番が問題となってGLSL3にするとコンパイルエラーとなっていました. 結局 ShaderMaterial の extensions で derivatives を有効にすることで対応できました.
基本的に Three.js と同様に GLSL3 への対応はマクロを使って対応し、シェーダコードは以前のままになっているのですが、MRTを使った部分だけは layout(location)
を使っています.GLSL3 では gl_FlagData
は使えないので.
WebGLRenderer.render()
引数に WebGLRenderTarget を渡すことが出来たのですが、それが出来なくなっていました.なので、setRenderTarget
で設定するようにしました.
おわりに
Three.js の対応というよりかは ESModule などの JavaScript 関連や開発環境周りの情報更新の方が大変だった気がします. 以上です.