UnityのシェーダーとParticleSystemを利用した「炎エフェクト」の作成方法

はじめに

UnityのシェーダーとParticleSystemを組み合わせて以下のような炎エフェクトを作成する方法を解説します。

 

今回作成する炎エフェクト

 

サンプル

STYLY GALLERYからサンプル空間を体験できます。

 

記事で紹介しているUnityプロジェクトのダウンロードはこちらからできます。

ダウンロードしたzipファイルを解凍し、「STYLY_Examples」→「ShurikenShader_Fire」フォルダ内のUnityプロジェクトが今回作成する炎シェーダーの完成形です。

Shuriken_Shager_Fire

Shuriken_Shager_Fire

使用するテクスチャ

今回は、以下のようなグレースケールテクスチャを使用します。

使用するテクスチャ

使用するテクスチャ

テクスチャの二値化

テクスチャカラーがしきい値を下回る部分は黒く、しきい値を上回る部分は白くするようなテクスチャ二値化を行います。

0.75で二値化

0.75で二値化


0.5で二値化

0.5で二値化


0.25で二値化

0.25で二値化

テクスチャをしきい値(Threshold)で二値化するようなシェーダーコードは以下のようになります。

color = step(Threshold, color)

 

しきい値の時間変化

今回作成する炎エフェクトでは、時間経過でしきい値を変化させて粒子の形状を変化させます。

しきい値を時間経過で変化させる

 

テクスチャ二値化シェーダー作成

ParticleSystemから二値化のしきい値のコントロールを行えるシェーダーの作成方法を解説します。

frag関数

ParticleSystemのCustom Vertex Streamsという仕組みを利用することで、シェーダーへ値を渡せます。

今回はParticleSystemから流れてくる数値を i.texcoord2.x で取得し、これをテクスチャ二値化のしきい値として利用するようなシェーダーを作成します。

fixed4 frag(v2f i) : SV_Target
{
fixed4 texColor = i.color * tex2D(_MainTex, i.texcoord);
fixed4 col = i.color * step(i.texcoord2.x, texColor.r);
...

 

シェーダー全体

 シェーダーコード(.shader)の全体は以下のようになります。Shader "Custom/Particles/Alpha Crunch - Alpha Blended" {
Properties{
_MainTex("Grayscale Texture", 2D) = "white" {}
}

Category{
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" }
Blend SrcAlpha OneMinusSrcAlpha // Alpha Blended
ColorMask RGB
Cull Off Lighting Off ZWrite Off

SubShader {
Pass {

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_particles
#pragma multi_compile_fog

#include "UnityCG.cginc"

sampler2D _MainTex;
fixed4 _TintColor;

struct appdata_t {
float4 vertex : POSITION;
fixed4 color : COLOR;
float4 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct v2f {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float2 texcoord2 : TEXCOORD1;
UNITY_FOG_COORDS(1)
UNITY_VERTEX_OUTPUT_STEREO
};

float4 _MainTex_ST;

v2f vert(appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.color;
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
o.texcoord2.xy = v.texcoord.zw; // Copy TEXCOORD0.zw
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}

fixed4 frag(v2f i) : SV_Target
{
fixed4 texColor = i.color * tex2D(_MainTex, i.texcoord);
fixed4 col = i.color * step(i.texcoord2.x, texColor.r);
col.rgb *= col.a;
UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0,0,0,0)); // fog towards black due to our blend mode
return col;
}
ENDCG
}
}
}
}

エフェクトの作成

作成したシェーダーを利用して、エフェクトを作成する方法を解説します。

 

ParticleSystemの作成

ParticleSystem作成

ParticleSystem作成

マテリアルの設定

上記のシェーダーからマテリアルを作成し、Rendererモジュールに登録します。

Rendererモジュールにマテリアルを設定

Rendererモジュールにマテリアルを設定

 

結果

ParticleSystemへマテリアルを設定すると、以下のように白い四角の粒子が飛ぶようになります。

Materialの設定直後

Custom Dataの設定

Custom Dataを利用して、二値化のしきい値として使うためのFloat値を定義します。

ここで定義したFloat値は後にシェーダー側へ渡されます。

 

Custom Dataを有効にする

Custom Dataのチェックを入れる

Custom Dataのチェックを入れる

 

Vectorデータの設定

Disableと表示されている部分をクリックし、Vectorを選択します。

Mode を Vectorへ設定

Mode を Vectorへ設定

 

Float値が4つ出てきますが、今回はFloat値を1つだけ使うのでNumber of Components を1に設定します。

Number of Componentsが4になっている

Number of Componentsが4になっている

結果

Custom DataのCustom1にFloat値が1つある状態になりました。

Number of Componentsを1に設定

Number of Componentsを1に設定

 

パラメータの名前を変える

パラメータ名がXだと分かりづらいので、Xの部分をクリックしてThreshold(しきい値)という名前を入れておきます。

パラメータ名をThresholdにしておく

パラメータ名をThresholdにしておく

 

Custom Vertex Streams の設定

次に、Custom Dataをシェーダーへ渡すための設定を行います。

 

Custom Vertex Streamsを有効にする

Rendererモジュールの中にあるCustom Vertex StreamsのチェックをONにします

Custom Vertex Streams

Custom Vertex Streams

 

チェックをONにすると、ストリームのリストが出現します。 

ParticleSystemからシェーダーへ渡したいデータはここで定義します。

Custom Vertex Streams

Custom Vertex Streams

 

データをストリームへ登録

リストの右下にある、+ボタンをクリックします。

+ボタンをクリック

+ボタンをクリック

 

今回はCustomDataのCustom1のX成分を登録したいので、 Custom -> Custom1.xを選択します。

Custom1を選択

Custom1を選択

 

Custom1.xがCustom Vertex Streamsへ追加され、TEXCOORD0.z経由でシェーダーへ値が流れるようになりました。 シェーダーからTEXCOORD0.zの値を参照したい場合、i.texcoord2.xを参照します。

Custom1.xが追加される

Custom1.xが追加される

以上で、Custom Vertex Streamsの設定は完了になります。

 

しきい値を変えたときのパーティクルの変化

Custom DataのThresholdの値を変更すると、パーティクルの見た目も変化します。

ここのThresholdはシェーダー内で以下のような二値化計算のしきい値として利用されています。 (実際はThresholdはi.texcoord2.xとしてシェーダーへ渡されています。)

fixed4 col = i.color * step(Threshold, texColor.r);

Threshold = 0.25

Threshold = 0.25


Threshold = 0.5

Threshold = 0.5

 

しきい値を時間変化させる

次に、このThresholdを時間で変化させるようにしてみます。

Thresholdの右側にある三角のアイコンをクリックします。

三角形のアイコンをクリック

三角形のアイコンをクリック

Curveを選択します。

Curveを選択

Curveを選択

 

Curveの設定

Curveの設定

Curveに設定すると、時間変化でパーティクルの形状が以下のように変化します。

Thresholdの時間変化

 

炎エフェクトの作成

今回作成したシェーダーを利用して、以下のような炎エフェクトを作成する方法を解説します。

オレンジ色の炎エフェクト + 黄色の炎エフェクトという二つの要素から構成されています。

作成する炎エフェクト

 

1つめのエフェクトを作成

炎の外側の部分を作成していきます。

作成するエフェクト

作成するエフェクト

Particle System作成

Particle Systemを作成し、名前をFire_Redとします。

ParticleSystemの作成

ParticleSystemの作成

基本モジュール

Start Lifetime, Start Size, Start Rotationをランダムに値に設定し、粒子にばらつきを持たせます。

基本モジュール

基本モジュール

 

Emissionモジュール

Emissionモジュールでは、粒子の発生数を設定します。

Emissionモジュール

Emissionモジュール

 

Shapeモジュール

Shapeモジュールでは、粒子の発生位置を設定します。

Shapeモジュール

Shapeモジュール

今回は発生位置に小さなばらつきを持たせるため、Radiusに小さな値を設定しています。

 

Velocity over Lifetimeモジュール

Velocity over Lifetimeモジュールでは、時間経過での粒子スピードの変化を設定します。

Velocity over Lifetimeモジュール

Velocity over Lifetimeモジュール

 

XYZ成分はそれぞれ以下のように設定しています。

Velocity over Lifetimeモジュール

Velocity over Lifetimeモジュール

粒子は最初にガス燃焼の加熱によって加速しながら上昇し、そのあとは空気冷却によって減速するようなイメージでスピードを設定しています。
空気の乱気流をイメージして、XY方向のスピードにもばらつきを持たせています。

 

Size over Lifetimeモジュール

最初はわずかに膨張し、そのあと少しずつ収縮していくようなイメージでサイズ変化を設定します。

Size over Lifetimeモジュール

Size over Lifetimeモジュール

 

Rotation over Lifetimeモジュール

粒子にランダムな回転の動きを持たせることで、エフェクトの動きをより複雑にします。

Rotation over Lifetimeモジュール

Rotation over Lifetimeモジュール

 

Custom Dataモジュール

エフェクトの後半で、粒子の形状がじわじわと粒子が削れていくようなイメージで Thresholdのカーブを設定します。

Custom Dataモジュール

Custom Dataモジュール

 

Rendererモジュール
Rendererモジュール

Rendererモジュール

オレンジ色の炎は黄色い炎より後ろに表示したいので、Sorting Fudgeの値を増やしておきます。

 

一つ目の要素が完成

オレンジ色の炎エフェクト(Fire_Red)が完成しました。

一つ目の要素

 

2番目のエフェクトを作成

炎の内部の部分のエフェクトを作成していきます。

二つ目の炎

 

Particle System作成

最初に作成した Fire_Redを複製し、Fire_Yellowという名前にします。

 

基本モジュールの設定

エフェクトのバラつきを意識しつつ、最初のエフェクトより短いLifetimeを設定します。

基本モジュール

基本モジュール

Emissionモジュール
Emissionモジュール

Emissionモジュール

Shapeモジュール
Shapeモジュール

Shapeモジュール

 

Velocity Over Livetimeモジュール
Velocity Over Livetimeモジュール

Velocity Over Livetimeモジュール

 

Size over Lifetime モジュール
Size over Lifetime モジュール

Size over Lifetime モジュール

 

Rotation over Lifetimeモジュール
Rotation over Lifetimeモジュール

Rotation over Lifetimeモジュール

 

Custom Dataモジュール
Custom Dataモジュール

Custom Dataモジュール

 

Rendererモジュール

今回の黄色い炎は、オレンジの炎の手前に表示したいのでSorting Fudgeを0に設定します。

Sorting Fudge = 0に設定

Sorting Fudge = 0に設定

 

2番目のエフェクトが完成

以下のような黄色い炎エフェクト(Fire_Yeloow)が完成しました。

完成したFire_Yellow

完成したFire_Yellow

 

 

Fire_RedとFire_Yellowを合わせる

空のParticleSystemを作成し、その中へFire_RedとFire_Yellowを入れることで
エフェクトが同時に再生されるようになります。

 

空のParticleSystem作成

ParticleSystemを作成し、名前をFX_Fireとします。

ParticleSystem作成

ParticleSystem作成

FX_Fireではパーティクルを発生させたくないのでモジュールをすべてOFFにします。

モジュールはすべてOFF

モジュールはすべてOFF

FX_Fireの中にエフェクト二つを入れる

FX_Fireの中に。 Fire_RedとFire_Yellowを入れるとFire_RedとFire_Yellowが同時に再生されるようになります。

 

結果

以下のようなエフェクトになり、炎エフェクトの完成です。

作成した炎エフェクト

UnityからSTYLYにプレハブをアップロードする方法

作成した炎エフェクトをSTYLYにアップロードする手順を解説します。

Unityで作成した炎エフェクトをSTYLYにアップロードする手順は以下の通りです。

  1. FX_Fireをprojectウィンドウに移動してプレハブ化する
  2. UNITY PLUGIN FOR STYLYをインポート
  3. プレハブを右クリックして「Upload prefab or scene to STYLY」をクリック
  4. アップロード完了

詳細なアップロード方法は以下のマニュアル記事で解説しているので、よくわからないという方はこちらの記事をご参照ください。

STYLY Studioで確認

STYLY Studioで確認

お疲れ様でした。以上でシェーダーを利用した炎エフェクトの作り方解説は終わりです。