サイトのトップへ戻る

libGDX ドキュメント 日本語訳

サイト内検索

3D パーティクルエフェクト

遠近感と深度に関する問題のために、2D のパーティクルエフェクトは3D アプリケーションには適していません。 さらに、3D のパーティクルエフェクトは3D空間での動きを最大限に活用し、様々な動的グラフィックエフェクトを使用できます。



Flame - 3D パーティクルエディター

2D のパーティクルエフェクトと同じ様に、3D のパーティクルエフェクトもlibgdxに実装されたGUIエディタで編集できます。 エディタの名前はFlameで、non-coreの gdx-tools.jar内にあります。 libgdx のリポジトリをクローンしている場合、dist ディレクトリで以下のコマンドを使うことでこのエディタを実行できます:

Linux/Mac:


java -cp gdx.jar:gdx-natives.jar:gdx-backend-lwjgl.jar:gdx-backend-lwjgl-natives.jar:extensions/gdx-tools/gdx-tools.jar com.badlogic.gdx.tools.flame.FlameMain

Windows:


java -cp gdx.jar;gdx-natives.jar;gdx-backend-lwjgl.jar;gdx-backend-lwjgl-natives.jar;extensions/gdx-tools/gdx-tools.jar com.badlogic.gdx.tools.flame.FlameMain



パーティクルエフェクトの種類

3Dパーティクルエフェクトには三つの種類があります:

  • Billboards
  • PointSprites
  • ModelInstance

Billboards は、常にカメラの方を向いてるSpriteです(libgdxの Decal クラスは本質的にはbillboardです)。

PointSprites は1つの3Dの点にSpriteを描写します。 billboardsよりも簡単ですが、より効率的です。 以下の動画での塵や爆発のエフェクトは、PointSpritesでしょりしたものです: 3D 戦車バトルの動画。 OpenGLにおけるポイントスプライトの詳細については、以下を参照してください: http://www.informit.com/articles/article.aspx?p=770639&seqNum=7

libgdxで3D作業をしたことがあれば、ModelInstancesについてはよく知っているでしょう。 ModelInstancesは3Dモデルのインスタンスです。 当然のことながら、これはパフォーマンスの面において最も苦労の多いパーティクルエフェクトです。

こうした違いのため、各タイプのパーティクルエフェクトには専用のバッチレンダラー: BillboardParticleBatchPointSpriteParticleBatchModelInstanceParticleBatchがあります。




3D パーティクルエフェクトを使用する

3D パーティクルエフェクトを使用する最も簡単な方法は、ParticleSystemクラスを活用することです。様々な詳細部分を抽象化し、それらをあなたに代わって管理してくれます。 まずは使用したい種類のバッチを作成し、それからParticleSystemを作成します。今回はPointSpritesを使用することにします。

3dパーティクルをプログラム上から使用する方法の詳細については、 test クラスを見てください

重要: 統合開発環境にParticleEffectクラスをインポートした時、誤って2D エフェクトの ParticleEffectクラスをインポートしないようにしてください。 2Dと3Dでは名前が同じですが、インポートパスが異なります。3Dの場合はこれ: com.badlogic.gdx.graphics.g3d.particles.ParticleEffectになります。



ステップ 1: Batchと ParticleSystemを作成する

// ParticleSystem is a singleton class, we get the instance instead of creating a new object:
ParticleSystem particleSystem = ParticleSystem.get();
// Since our particle effects are PointSprites, we create a PointSpriteParticleBatch
PointSpriteParticleBatch pointSpriteBatch = new PointSpriteParticleBatch();
pointSpriteBatch.setCamera(cam);
particleSystem.add(pointSpriteBatch);


ステップ 2: AssetManagerを使用してエフェクトを読み込む

ここで、 Flame GUIエディターを使って作成したパーティクルエフェクトを読み込む必要があります。 まず、ロード時にアセットマネージャーへ渡すためのParticleEffectLoadParameterを作成します。 それからアセットを読み込みます。

AssetManager assets = new AssetManager();
ParticleEffectLoader.ParticleEffectLoadParameter loadParam = new ParticleEffectLoader.ParticleEffectLoadParameter(particleSystem.getBatches());
assets.load("particle/effect.pfx", ParticleEffect.class, loadParam);
assets.finishLoading()


Step 3: 読み込んだ ParticleEffectを ParticleSystemへ追加する

ParticleEffect originalEffect = assets.get("particle/effect.pfx");
// we cannot use the originalEffect, we must make a copy each time we create new particle effect
ParticleEffect effect = originalEffect.copy();
effect.init();
effect.start();  // optional: particle will begin playing immediately
particleSystem.add(effect);

上に戻って3D 戦車バトルの動画を見ると、各戦車が独自に埃エフェクトを持っていることが分かるでしょう。 つまり、各戦車はシステム内でエフェクトの独自コピーを持っています。 必要なオブジェクトやグラフィカルエフェクトを作成する度にパーティクルエフェクトの新規コピーを作成するのは本当に煩わしいです。 代わりに、エフェクトのPoolを使用してオブジェクトの新規作成を避けることができます。 このwikiもしくはlibgdx Poolクラスのドキュメントでプール処理の詳細を読むことができます。

以下がPoolの例です:

private static class PFXPool extends Pool<ParticleEffect> {
	private ParticleEffect sourceEffect;

	public PFXPool(ParticleEffect sourceEffect) {
		this.sourceEffect = sourceEffect;
	}

	@Override
	public void free(ParticleEffect pfx) {
		pfx.reset();
		super.free(pfx);
	}

	@Override
	protected ParticleEffect newObject() {
		return sourceEffect.copy();
	}
}

取得時ではなく解放時にパーティクルをリセットしているので注意してください。 これにより、ParticleSystemの挙動が原因で発生するNullPointerExceptionを回避することができます。



ステップ 4: ParticleSystemを使って 3D パーティクルを描写する

ParticleSystem では自身のコンポーネントの更新と描写を行い、ModelBatch インスタンスへ引数として渡してシーンへ描写する必要があります。

private void renderParticleEffects() {
	particleSystem.update(); // technically not necessary for rendering
	particleSystem.begin();
	particleSystem.draw();
	particleSystem.end();
	modelBatch.render(particleSystem);
}

また、エフェクトの移動と回転を行うこともできます。 Depending on how your engine works you might want to use a specific matrix that is reset to identity on changes or only add the delta transformation/rotation.

private void renderParticleEffects() {
	targetMatrix.idt();
	targetMatrix.translate(targetPos);
	effect.setTransform(targetMatrix);
	particleSystem.update(); // technically not necessary for rendering
	particleSystem.begin();
	particleSystem.draw();
	particleSystem.end();
	modelBatch.render(particleSystem);
}

もしくは

private void renderParticleEffects() {
	effect.translate(deltaPos);
	particleSystem.update(); // technically not necessary for rendering
	particleSystem.begin();
	particleSystem.draw();
	particleSystem.end();
	modelBatch.render(particleSystem);
}


新規パーティクルの放出を停止し、既存パーティクルの再生を終了させる

3D パーティクルシステムでこれを行うことは少し複雑です:

Emitter emitter = pfx.getControllers().first().emitter;
		if (emitter instanceof RegularEmitter) {
			RegularEmitter reg = (RegularEmitter) emitter;
			reg.setEmissionMode(RegularEmitter.EmissionMode.EnabledUntilCycleEnd);
		}


全使用例 (外部ソース)

使用例は全て(https://drive.google.com/file/d/0BwiuGlZ9rT-bRm9zQlJHbzFCWWs/edit?usp=sharing)にあります

メインクラスは core/sbourges/game/gdxtest/GdxTest.java です



簡単な例

上記 GdxTest.java の簡単な使用例は ここにあります。