Version: Unity 6.0 (6000.0)
言語 : 日本語
カスタムシェーダーのパーティクルシステム GPU インスタンシング
ビルトインレンダーパイプラインの Autodesk Interactive シェーダー

カスタム頂点ストリームを使用したパーティクルシステム GPU インスタンシングの例

前出の例では、パーティクルのデフォルトの頂点ストリーム設定のみを使用しています。これには、位置、法線、色、1 つの UV が含まれます。ただし、カスタム頂点ストリームを使用することによって、速度、回転、サイズなど、他のデータをシェーダーに送信できます。

次の例では、シェーダーは特殊効果を表示するように設計されています。これにより、高速なパーティクルは明るく表示され、低速なパーティクルは暗く表示されます。スピード頂点ストリームを使用して、スピードに応じてパーティクルを明るくする追加のコードが存在します。また、このシェーダーは効果がテクスチャシートアニメーションを使用しないと仮定するため、カスタムストリーム構造体から除外されます。

以下は、完全なシェーダーです。

Shader "Instanced/ParticleMeshesCustomStreams"
{
    Properties
    {
        _MainTex("Albedo", 2D) = "white" {}
    }
    SubShader
    {
        Tags{ "RenderType" = "Opaque" }
        LOD 100
        Pass
        {
            CGPROGRAM
#pragma exclude_renderers gles
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #pragma instancing_options procedural:vertInstancingSetup
            #define UNITY_PARTICLE_INSTANCE_DATA MyParticleInstanceData
            #define UNITY_PARTICLE_INSTANCE_DATA_NO_ANIM_FRAME
            struct MyParticleInstanceData
            {
                float3x4 transform;
                uint color;
                float speed;
            };
            #include "UnityCG.cginc"
            #include "UnityStandardParticleInstancing.cginc"
            struct appdata
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
            };
            sampler2D _MainTex;
            float4 _MainTex_ST;
            v2f vert(appdata v)
            {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v);
                o.color = v.color;
                o.texcoord = v.texcoord;
                vertInstancingColor(o.color);
                vertInstancingUVs(v.texcoord, o.texcoord);
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
                UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
                o.color.rgb += data.speed;
#endif
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                half4 albedo = tex2D(_MainTex, i.texcoord);
                return i.color * albedo;
            }
            ENDCG
        }
    }
}

シェーダーには、カスタム頂点ストリームが使用されていないときのデフォルトのインスタンシングデータレイアウトを含む UnityStandardParticleInstancing.cginc が配置されています。そのため、カスタムストリームを使用する場合は、対象のヘッダーで定義されているデフォルト設定のいくつかをオーバーライドする必要があります。これらのオーバーライドは include の に配置する必要があります。上の例では、次のカスタムオーバーライドを設定しています。

最初に、UNITY_PARTICLE_INSTANCE_DATA マクロを使用して、カスタムストリームデータのための ‘MyParticleInstanceData’ というカスタム構造体を使用するよう指示しています。

            #define UNITY_PARTICLE_INSTANCE_DATA MyParticleInstanceData

次に、もう 1 つの定義で、Anim Frame Stream (アニメーションフレームストリーム) がこのシェーダーで必要でないことをインスタンシングシステムに伝えています。なぜなら、この例の効果はテクスチャシートアニメーションでの使用を意図していないためです。

            #define UNITY_PARTICLE_INSTANCE_DATA_NO_ANIM_FRAME

第 3 に、カスタムストリームデータの構造体が宣言されます。

            struct MyParticleInstanceData
            {
                float3x4 transform;
                uint color;
                float speed;
            };

これらのオーバーライドはすべて UnityStandardParticleInstancing.cginc が配置されている箇所より前の位置に配置されているため、シェーダーはこれらの定義にシェーダー自体のデフォルト設定を使用しません。

構造体を記述する場合、変数は Particle System Renderer モジュールの Inspector にリストされている頂点ストリームと一致する必要があります。つまり、Renderer モジュールの UI で使用するストリームを選択し、カスタムストリームデータ構造体の変数定義に同じ順序で追加して、一致させる必要があります。

Renderer モジュールの UI に表示されたカスタム頂点ストリーム。インスタンス化されたストリームとインスタンス化されていないストリームの一部が表示されます。
Renderer モジュールの UI に表示されたカスタム頂点ストリーム。インスタンス化されたストリームとインスタンス化されていないストリームの一部が表示されます。

最初の項目 (Position) は必須であるため、削除することはできません。プラス (+) とマイナス (-) のボタンを使用して他のエントリーを自由に追加/削除して、頂点ストリームデータをカスタマイズできます。

リスト内で INSTANCED と示されるエントリーにはインスタンスデータが含まれているため、パーティクルインスタンスのデータ構造体に加える必要があります。INSTANCED という語のすぐ後に加えられた数字 (例: INSTANCED0 の 0 と INSTANCED1 の 1) は、最初の “transform” 変数のに、変数を構造体に配置する順序を示します。末尾の文字 (.x .xy .xyz .xyzw) は、変数の型を示し、シェーダーコードの float、float2、float3、float4 変数の型にマップされます。

リストに表示されていて、INSTANCED と 示されて いない 他の頂点ストリームデータは、パーティクルインスタンスのデータ構造体から削除できます。これは、それらがシェーダーによって処理されるインスタンス化されたデータではないためです。このデータは、UV、法線、接線などのソースメッシュに属します。

例を完成させる最後の手順は、頂点シェーダー内のパーティクルの色に速度を適用することです。

#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
                UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
                o.color.rgb += data.speed;
#endif

すべてのインスタンシングコードを UNITY_PARTICLE_INSTANCING_ENABLED のチェック内にラップする必要があります。そのようにすると、インスタンス化が使用されていないときにもコンパイルできます。

この時点で、フラグメントシェーダーにデータを渡したい場合は、他のシェーダーデータの場合と同様に、v2f 構造体にデータを書き込むことができます。

この例では、カスタムの頂点ストリームで使用するカスタムシェーダーを変更する方法について説明しますが、サーフェスシェーダーにも全く同じアプローチで同じ機能を実現できます。

カスタムシェーダーのパーティクルシステム GPU インスタンシング
ビルトインレンダーパイプラインの Autodesk Interactive シェーダー