TSL · WebGPU · Three.js

コードとして記述するVFXを、
Niagaraのようにスケジュールする。

組み合わせ可能なパーティクルモジュール、タイムライン、流体グリッド、近傍シミュレーション、 デバッグ機能 — エディタランタイムを必要としない。

はじめに

インストールから最初のバーストまで

01

インストール

pnpm add @nachi-vfx/core @nachi-vfx/three three@0.185.1
pnpm add -D @types/three@0.185.0 # TypeScript
02

インポートして定義する

import {
  VFXSystem, billboard, burst, defineEffect,
  defineEmitter, drag, gravity, lifetime,
  positionSphere,
} from '@nachi-vfx/core'
import {
  createThreeKernelAdapter,
  createThreeRuntimeRenderer,
  materializeThreeSpriteDraw,
} from '@nachi-vfx/three'
import * as THREE from 'three/webgpu'

const sparks = defineEmitter({
  capacity: 512,
  spawn: burst({ count: 120 }),
  init: [positionSphere({ radius: .2 }), lifetime(.8)],
  update: [gravity(-9.8), drag(.35)],
  render: billboard({ blending: 'additive' }),
})

const effect = defineEffect({ elements: { sparks } })
03

マテリアライズして再生する

const renderer = new THREE.WebGPURenderer()
renderer.setSize(innerWidth, innerHeight)
document.body.append(renderer.domElement)
await renderer.init()

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
  50, innerWidth / innerHeight, .1, 100,
)
camera.position.set(0, 1, 5)

const adapter = createThreeKernelAdapter({ backend: 'webgpu' })
const runtimeRenderer = createThreeRuntimeRenderer(renderer, adapter)
const system = new VFXSystem(runtimeRenderer, scene)
const instance = system.spawn(effect, { position: [0, 1, 0], seed: 42 })
const emitter = instance.getEmitter('sparks')
if (!emitter) throw new Error('Missing sparks emitter')
const draw = materializeThreeSpriteDraw(emitter.program, emitter.kernels)
scene.add(draw)

let previous = performance.now()
async function frame(now) {
  await system.update(Math.min((now - previous) / 1000, .1))
  previous = now
  renderer.render(scene, camera)
  requestAnimationFrame(frame)
}
requestAnimationFrame(frame)

リポジトリのPagesデプロイでは、このドキュメントルート以下にplaygroundとshowcaseを配置する。 docsを単独でデプロイする場合はリンク先URLを設定するか、デモへのリンクを省略すること。 上記のnpm Quick Startはplaygroundに依存しない。

コアガイド

作成フローの全体像

エミッター

容量を選び、決定的なバースト・レート・距離スポーンから選択する。ライフサイクル、 プリウォーム、ループ、バウンズ、品質は宣言的に扱われる。

モジュール

InitとUpdateの挙動を記述順に合成する。アクセスマニフェストにより、動的な属性や カスタムのTSLスクラッチモジュールを検査可能にする。

タイムライン

エフェクトローカルなクロック上で、再生・停止・マーカー・カメラシェイク・ヒットストップを 決定的なループ境界とともにシーケンスする。

メッシュエフェクト

fxMaterialで、スクロールするマップ、独立したディゾルブUV、実行時opacity、 エッジ発光を合成する。ホールド閾値はノイズテクスチャ値域の下限未満に置き、 ノイズ周波数はメッシュスケールに合わせる。

スケーラビリティ

4段階の品質ティア、距離/フラスタムカリング、重要度スコア、パーティクル予算、 上限付きリソースプールを使用する。

シミュレーションキャッシュ

レンダラーが読み取る属性をFloat32または量子化されたバイナリスナップショットへ ベイクし、シミュレーションカーネルをスケジュールせずにリプレイする。

デバッガー

シリアライズされたシステムキューを通じて論理パーティクル行とフレームローカルな プロファイルをキャプチャする。取得できないGPUタイミングは明示的に示される。

グリッド流体

インジェクション、アドベクション、浮力、Jacobi圧力、プロジェクションのための パック済みGrid2D/3Dステージを実行する。

近傍(Neighbors)

フロッキング、カスタム近傍TSL、反復的なJacobi PBD距離制約のための、 上限付きGPU近傍グリッドを構築する。

APIリファレンス

利便性より先に、契約(コントラクト)を。

規範的なRFC文書が、ステージのセマンティクス、ランタイムの所有権、診断、シリアライズ、 パッケージ境界を定義する。各パッケージのREADMEは、的を絞った入り口を提供する。