PixiJS v8のマイグレーションガイドを読んでみる
この記事は
PixiJSの8系がリリースされた。WebGPU対応でなんだかメチャ速らしい。
かんたんなものだけどPixiJSでゲームを作ってるので移行できるなら移行したい。
公式がマイグレーションガイド v8 Migration Guide | PixiJS を出してくれているので今日はこれを読む。
あくまで個人的な備忘録であり翻訳ではない。正確性も保証しない。
※2024/04/12 時点のガイド これは公式リポジトリのWikiに移動して更新される可能性がある。
1.イントロ
WebGPUに対応したりしてメチャ速くなりました。
2.破壊的な変更
破壊的な変更やまだ対応完了していないPixiプラグインもあるので過去バージョンから移行する場合には検討が必要です。
移行が難しいかもしれない人
- 数万個単位のパーティクルを描画するために
ParticleContainer
を使っている人
- 独自バッチレンダラーを使っている人(v8には独自バッチを組み込む機能はまだない でもロードマップにはある)
- v8で未対応のPixiライブラリを使っている人
- 統合済み
- Filters
- Sound
- Gif
- Storybook
- UI
- Open Games??(しらない)
- 近々対応予定
- React
- Spine
- そのうち…
- Pixi layers(プラグインとしてではなく基本機能としてv8に組み込み予定)
- 統合済み
新パッケージストラクチャ
パッケージを小分けにしすぎたので単一パッケージに戻しますとのこと。
Old:
import { Application } from '@pixi/app'; import { Sprite } from '@pixi/sprite';
New:
import { Application, Sprite } from 'pixi.js';
カスタムビルド
今までextensions扱いだったものがデフォルトでインポートされるようになったけど、それらをインポートしたくない場合は手動でimport
書いてねってことみたい?
非同期イニシャライズ
WebGPUの導入によりApplication
を生成後に非同期のinit()
待ちが必要になったらしいです。
ApplicationOptions
オブジェクトはコンストラクタでなくinit()
に渡せとのこと。
Old:
import { Application } from 'pixi.js'; const app = new Application(); // do pixi things
New:
import { Application } from 'pixi.js' const app = new Application(); (async () => { await app.init({ // application options }); // do pixi things })()
コメント
クラスのコンストラクタ内でApplication
を初期化してる場合とか非同期builder作らなきゃいけなくなってめんどくさそう
Texture
の調整
ちょっと何言ってるかよくわからないセクション。
Texture
がリソースを管理する必要はなく、これらは事前にアセットマネージャーが行う仕事。
BaseTexture
は廃止された。
代わりにTextureSource
が追加された。これはテクスチャの設定とアップロード,使用する方法をまとめたもの。(??)
テクスチャソースにはいろいろある
- TextureSource
- ImageSource
- CanvasSource
- VideoSource
- BufferSource
- CompressedSource
基本的にはAssets
がTexture
を返すとのこと。
コメント
Texture
側から自身がロード済みかどうか気にする必要がなくなったってこと…?v7の時点でそんな感じじゃなかったっけ…
BaseTexure
がなくなって色んなタイプのTextureSource
が追加されたよ!っていうのがメインなのかな… Sprite
生成くらいにしかTexture
をつかってないのでよくわからん…
Graphics
APIの改修
Graphics
を生成するときの記述の順序が変わった。
beginFill()
→ 形状描画 → endFill()
から
形状描画 → 塗りつぶし,ストロークになった。
Old:
// red rect const graphics = new Graphics() .beginFill(0xFF0000) .drawRect(50, 50, 100, 100) .endFill(); // blur rect with stroke const graphics2 = new Graphics() .lineStyle(2, 'white') .beginFill('blue') .circle(530, 50, 140, 100) .endFill();
New:
// red rect const graphics = new Graphics() .rect(50, 50, 100, 100) .fill(0xFF0000); // blur rect with stroke const graphics2 = new Graphics() .rect(50, 50, 100, 100) .fill('blue') .stroke({width:2, color:'white'});
そのほかGraphics関連変更
詳しくは原文で
- 形状描画関連のメソッド名も変わった。引数は変わらない。(
drawCirecle()
→circle()
など)
- 塗りつぶし系のメソッドは引数が
(色, アルファ値)
的な形から({color:色, alpha:アルファ値})的な形でそれぞれの型のオブジェクトを渡すようになった。
-
hole
がcut
になって使いやすくなった -
GraphicsGeometry
はGrahpicsContext
に置き換え
コメント
全部書き直すのめんどくせ~~~~~~~
シェーダーの変更
シェーダー周りは知識不足で嘘を書く可能性があるので原文ままで引用します。
As we now need to accommodate both WebGL and WebGPU shaders, the wey they are constructed has been tweaked to take this into account. The main differences you will notice (this is for shaders in general) is that Textures are no longer considered uniforms (as in they cannot be included in a uniform group). Instead we have the concept of resources. A resource can be a few things including:
TextureSource - A source texture myTexture.source TextureStyle - A texture style myTexture.style UniformGroup - A collection of number based uniforms myUniforms = new UniformGroup({}) BufferResource - A buffer that is treated as a uniform group (advanced)
creating a webgl only shader now looks like this:
old
const shader = PIXI.Shader.from(vertex, fragment, uniforms);
new
just WebGL
const shader = Shader.from({ gl: { vertex, fragment }, resources, // resource used from above including uniform groups });
WebGL and WebGPU
const shader = Shader.from({ gl: { vertex, fragment }, gpu: { vertex: { entryPoint: 'mainVert', source, }, fragment: { entryPoint: 'mainFrag', source, }, }, resources, // resource used from above including uniform groups });
Uniforms are also constructed in a slightly different way. When creating them, you now provide the type of variable you want it to be.
old
const uniformGroup = new UniformGroup({ uTime:1, }); uniformGroup.uniforms.uTime = 100;
new
const uniformGroup = new UniformGroup({ uTime:{value:1, type:'f32', }); uniformGroup.uniforms.uTime = 100; // still accessed the same!
The best way to play and fully and get to know this new setup please check out the Mesh and Shader examples:
old: v7 example new: v8 example
フィルター
フィルターの動きはほぼ変わらないけどカスタムフィルターを作る場合は前セクションのシェーダーの変更を考慮してねとのこと。
old
const filter = new Filter(vertex, fragment, { uTime: 0.0, });
new
const filter = new Filter({ glProgram: GlProgram.from({ fragment, vertex, }), resources: { timeUniforms: { uTime: { value: 0.0, type: 'f32' }, }, }, });
そのほかの破壊的な変更
-
DisplayObject
廃止Contaier
がPixiオブジェクトの基底クラスになります。 ※マジか…
-
updateTransform()
を廃止。フレームごとに何か処理したい場合にはonRender()
を用意したのでこっちを使ってね。
- ミップマップ生成の変更(?? 原文見てください "Mipmap generation changes" の項)
- テクスチャのUVが変更された際にスプライトが通知を受け取れなくなった。基本的にテクスチャのUVは変更しない方がいい。
- UVを変更してアニメーションするような場合スプライトの更新は自身でやらないとダメ。ソースデータ(ビデオテクスチャなど)の変更は即座に反映される。
const texture = await Assets.load('bunny.png'); const sprite = new Sprite(texture); texture.frame.width = texture.frame.width/2; texture.update(); // guarantees the texture changes will be reflected on the sprite sprite.onViewUpdate(); // alternatively you can hooke into the sprites event texture.on('update', ()=>{sprite.onViewUpdate});
-
Container
のカリング動作を変更。カリングはレンダリングループ内で自動で行われていたが、これは廃止し、ユーザー自身で制御させるようにした。
関連していくつかのプロパティを追加。-
cullable
- コンテナがカリング可能か否か -
cullArea
- カリング領域をコンテナ全体としたくない場合にこれでカリング領域を指定する -
cullableChildren
- 子要素をカリング可能とするか否か
-
const container = new Container(); const view = new Rectangle(0, 0, 800, 600); container.cullable = true; container.cullArea = new Rectangle(0,0,400,400); container.cullableChildren = false; Culler.shared.cull(myContainer, view); renderer.render(myContainer);
以前と同様の動作をさせたい場合は、CullerPlugin
が使える。これは毎フレームCuller.shared.cull
を実行する。
import {extensions, CullerPlugin} from 'pixi.js' extensions.add(CullerPlugin)
- いくつかのメッシュクラスをリネーム
- SimpleMesh -> MeshSimple
- SimplePlane -> MeshPlane
- SimpleRope -> MeshRope
-
Assets
のdeprecatedな使い方を廃止 ※地味にめんどい…
Old:
import { Assets } from 'pixi.js'; Assets.add('bunny', 'bunny.png');
New:
import { Assets } from 'pixi.js'; Assets.add({ alias: 'bunny', src: 'bunny.png' });
-
PIXI.settings
の廃止
Old:
import { settings, BrowserAdapter } from 'pixi.js'; settings.RESOLUTION = 1; settings.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT = false; settings.ADAPTER = BrowserAdapter;
New:
import { AbstractRenderer, DOMAdapter, BrowserAdapter } from 'pixi.js'; // Can also be passed into the renderer directly e.g `autoDetectRenderer({resolution: 1})` AbstractRenderer.defaultOptions.resolution = 1; // Can also be passed into the renderer directly e.g `autoDetectRenderer({failIfMajorPerformanceCaveat: false})` AbstractRenderer.defaultOptions.failIfMajorPerformanceCaveat = false; // See below for more information about changes to the adapter DOMAdapter.set(BrowserAdapter);
※SCALE_MODE
なんかは存在がなくなってた
-
アダプターとWebWorkerの変更
-
settings.ADAPTER
は廃止。DOMAdapter
で置き換え - 詳しくは原文参照("Adapter and Web Worker Changes" の項)
-
-
Application
生成時にレンダラーのタイプを明示できるようになった?
Old:
const app = new Application<HTMLCanvasElement>(); ```js New: ``` js // WebGL or WebGPU renderer const app = new Application<Renderer<HTMLCanvasElement>>(); // WebGL specific renderer const app = new Application<WebGLRenderer<HTMLCanvasElement>>(); // WebGPU specific renderer const app = new Application<WebGPURenderer<HTMLCanvasElement>>();
-
Texture.from()
にURLを渡してテクスチャをロードすることはできなくなった。URLからテクスチャ生成したい場合は一度await Assets.load(url)
してからTexture.from(url)
する必要がある。
-
Ticker
を使ったコールバックにはデルタタイムでなくTickerインスタンスを
渡すよう変更
Old:
Ticker.shared.add((dt)=> { bunny.rotation += dt });
New:
Ticker.shared.add((ticker)=> { bunny.rotation += ticker.deltaTime; });
※大量に使ってたりするとめんどくさそう…
-
テキストパーサーのリネーム
- TextFormat -> bitmapFontTextParser
- XMLStringFormat -> bitmapFontXMLStringParser
- XMLFormat -> bitmapFontXMLParser
-
デフォルトの
eventMode
がauto
からpassive
へ ※v6からあるinteractiveの拡張らしいけど使ったことない- 色々使い分けできそう Interaction > Event Modes
- 色々使い分けできそう Interaction > Event Modes
-
utils
廃止。utils
にあったものは本体をインポートすれば使える。
Old:
import { utils } from 'pixi.js'; utils.isMobile.any();
New:
import { isMobile } from 'pixi.js'; isMobile.any();
-
container.getBounds()
はRectangle
でなくBounds
を返すようになった。今まで通りに使いたい場合は、container.getBounds().rectangle
でRectangle
にアクセスできる。
-
ParticleContainer
の廃止。代わりに通常のContainer
を使ってほしい。WebGPU対応でパフォーマンスが上がったからもうParticleContainer
を使う必要ないよ。
3.非推奨となった仕様
deprecated
となった仕様たち。
v7の一部仕様もv8で廃止されたそうです。
- 葉ノードは子要素を持てなくなりました
- 子要素を持てるのは
Container
のみ。Sprite
やMesh
やGraphics
はだめ。 - 今まで通りに動作させたいなら親
Container
を作って子ともどもぶちこんでね。
- 子要素を持てるのは
Old:
const sprite = new Sprite(); const spriteChild = new Sprite(); sprite.addChild(spriteChild);
New:
const container = new Container(); const sprite = new Sprite(); const spriteChild = new Sprite(); container.addChild(sprite); container.addChild(spriteChild);
-
Application.view
はApplication.canvas
に置き換わりました
Old:
const app = new Application({ view: document.createElement('canvas') }); document.body.appendChild(app.view);
New:
const app = new Application(); await app.init({ view: document.createElement('canvas') }); document.body.appendChild(app.canvas);
-
NineSlicePlane
→NineSliceSprite
にリネーム ※Planeてなんじゃいと思ってはいた
-
SCALE_MODES
定数をScaleMode
文字列で置き換え- SCALE_MODES.NEAREST -> 'nearest'
- CALE_MODES.LINEAR -> 'linear'
-
WRAP_MODES
,DRAW_MODES
も同様 -
いずれも
settings
からは消えている
-
複数の引数を渡していたコンストラクタは、代わりにオブジェクトを渡すよう変更
例
Old:
const blurFilter = new BlurFilter(8, 4, 1, 5); const displacementFilter = new DisplacementFilter(sprite, 5); const meshGeometry = new MeshGeometry(vertices, uvs, index); const mesh = new Mesh(geometry, shader, state, drawMode); const plane = new PlaneGeometry(width, height, segWidth, segHeight); const nineSlicePlane = new NineSlicePlane(texture, leftWidth, topHeight, rightWidth, bottomHeight); const tileSprite = new TileSprite(texture, width, height); const text = new Text('Hello World', style); const bitmapText = new BitmapText('Hello World', style); const htmlText = new HTMLText('Hello World', style);
New:
const blurFilter = new BlurFilter({ blur: 8, quality: 4, resolution: 1, kernelSize: 5, }); const displacementFilter = new DisplacementFilter({ sprite, scale: 5, }); const meshGeometry = new MeshGeometry({ positions: vertices, uvs, indices: index, topology: 'triangle-list'; shrinkBuffersToFit: boolean; }); const mesh = new Mesh({ geometry shader texture }); const plane = new PlaneGeometry({ width, height, verticesX: segWidth, verticesY: segHeight, }); const nineSliceSprite = new NineSliceSprite({ texture, leftWidth, topHeight, rightWidth, bottomHeight, }); const tileSprite = new TileSprite({ texture, width, height, }); const text = new Text({ text: 'Hello World', style, }); const bitmapText = new BitmapText({ text:'Hello World', style, }); const htmlText = new HTMLText({ text:'Hello World', style, });
※Text系直すのめんどくせ~~~~~~~~~~~~~~~~
-
container.name
→container.label
にリネーム
4.資料
感想
変更が多い…!
がっつり使ってない人でもぼちぼちコード修正を強いられるかと思います。
爆速レンダリングをてにいれるためだ仕方ない…
Discussion