上級 20 min 18 / 20
ライブデモ
チュートリアル 18: プラグイン — フォークせずにレンダラーを拡張
レベル: 上級 時間: 20 分 学ぶこと:
@joroya/core/pluginsのプラグインシステムで、ThreeRendererを変更せずに新しいコンポーネントタイプを独自のレンダリング動作付きで出荷する方法。
安定性:
PluginRegistry、Plugin、ComponentHandlerは v1.0 で@experimental。
プラグインが必要なとき
組み込みレンダラーは Geometry、Material、Camera、Light、ParticleSystem、オーディオ、インスタンシング、スキンドメッシュを処理。それ以上 — ボクセルグリッド、カスタムシェーダー、GPU コンピュート出力、サードパーティーの物理ビジュアライザー — はプラグインの領域。
プラグインは小さなモジュール:
- カスタム
ComponentTypeまたは文字列 ID のComponentHandlerを定義。 create(node)からTHREE.Object3D(任意のバックエンドオブジェクト)を返す。- オプションで
update(node, obj, dt)でフレームごとの同期、dispose(node, obj)で GPU リソース解放。
レンダラーは組み込みブランチの前にレジストリにクエリ。
ステップ 1 — カスタムコンポーネントを定義
import { Component } from "@joroya/core";
export class VoxelGridComponent extends Component {
readonly type = "VoxelGrid";
constructor(
public readonly size: { x: number; y: number; z: number },
public readonly cellSize: number,
public readonly voxels: Uint8Array,
) { super(); }
}
ステップ 2 — ハンドラを書く
import type { ComponentHandler } from "@joroya/core";
import * as THREE from "three";
export const voxelHandler: ComponentHandler<THREE.Object3D> = {
componentType: "VoxelGrid",
create(node) {
// THREE.InstancedMesh を構築 — 非ゼロボクセルごとに 1 立方体
return mesh;
},
update(node, mesh, dt) { /* オプション */ },
dispose(node, mesh) { /* GPU リソース解放 */ },
};
ステップ 3 — Plugin としてバンドル + 登録
import type { Plugin } from "@joroya/core";
export const voxelPlugin: Plugin = {
name: "voxel-renderer",
handlers: [voxelHandler],
};
renderer.usePlugin(voxelPlugin);
プラグインの優先順位
- ノードの各コンポーネントに対してプラグインレジストリにクエリ。
- ハンドラが存在し非
nullを返したら、それが使われる。 nullを返したら、ノードの次のコンポーネントへフォールスルー。- どのハンドラもマッチしなければ、組み込みチェーンを実行。
プラグインはデフォルトを置き換える(オブジェクト返却)か、augment する(null 返却して update(dt) だけ受ける)。
Dispose ライフサイクル
renderer.rebuildScene() と renderer.dispose() は各プラグイン管理オブジェクトを走査し、handler.dispose(node, obj) を呼ぶ。ここで geometry.dispose() / material.dispose() / texture.dispose() を解放。
次のステップ
- マルチハンドラプラグイン: 同じパッケージから複数のコンポーネントタイプ用のハンドラを登録。
- プラグインを公開:
@<your-org>/oroya-plugin-voxels— 慣習はcomponentTypeの名前。