LoginSignup
4
2

More than 5 years have passed since last update.

UNITY DrawCall調査 particles GPU Instancing ~ UNITY2018.3.6f1 ~

Posted at

前回に続き、DrawCall削減で、ParticleのGPU Instancing関連を調査

ParticleSystem

Billboard

通常Particleを表示させると下記のようになる

SnapCrab_NoName_2019-3-5_2-45-18_No-00.png

SnapCrab_NoName_2019-3-5_2-45-34_No-00.png

DynamicBatchingが効いてちゃんと効率化されてます

ParticleSystemのRenderingを見てみましょう。
RenderModeがBillboardですね。BillboardではGPU Instancingは使えないが
DynamicBatchingでいいようにしてくれます

mesh

GPU Instancingを使うにはmeshにします
meshにすると、メッシュをパーティクルとして飛ばせます
デフォルトで Default-ParticleSystemというメッシュが付いています
そしてそのシェーダーはGPU Instancing対応しています

SnapCrab_NoName_2019-3-5_2-53-27_No-00.png

GPU Instancing無し

SnapCrab_NoName_2019-3-5_2-56-36_No-00.png

DynamicBatchingは効いてるが、GPU Instancingはありません

GPU Instancingあり

SnapCrab_NoName_2019-3-5_2-54-46_No-00.png

GPU Instancing効いてます

自作のマテリアルをつける

Shader "Instancing2"
{
        SubShader
    {
        Tags { "RenderType" = "Opaque" "DisableBatching" = "True"}

        Pass
        {
            Tags { "LightMode" = "ForwardBase" } 

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #pragma multi_compile_instancing
            #pragma instancing_options procedural:vertInstancingSetup

            #include "UnityCG.cginc"
            #include "UnityStandardParticleInstancing.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float4 color : COLOR;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 color : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            v2f vert(appdata v)
            {
                UNITY_SETUP_INSTANCE_ID(v);

                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.color = i.color;

                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                return i.color;
            }

            ENDCG
        }
        }
}

前回とほぼ同じだが、

#pragma instancing_options procedural:vertInstancingSetup

がないとちゃんと動かなかった。基本的にGPU Instancingを行う時は上記オプションをつけたほうがよさそうだ
また、Colorプロパティーに関するものは今回無いので削除した

SnapCrab_NoName_2019-3-5_3-10-30_No-00.png

ちゃんと効く

グラデーションをする

ParticleのパラメータでStartColorをグラデーションにしてみる
色が変わる=マテリアルが変わるので、普通に行うと色の数だけマテリアルが生成されると思うが

Default-ParticleSystem

SnapCrab_NoName_2019-3-5_3-15-15_No-00.png

グラデーションでパーティクルが表示されたが
DrawCallは GPU Instancingの有無にかかわらず単色の時と変わらない
何故だろうか?

自作メッシュ

メッシュを自作に変更する

GPU Instancing無しだとちゃんと表示されるが
有りにすると全部白いパーティクルになった

SnapCrab_NoName_2019-3-5_3-21-18_No-00.png

何かがおかしい

答えは、Instancingの仕組みにある
頂点属性や、プロパティーは INSTANCE_IDにより配列から値を取り出す
Positionは実は UnityObjectToClipPos の内部で計算されている
が、Colorはそのままなのでダメ
Colorの変換には vertInstancingColor という関数が用意されている

頂点シェーダーの Color代入部分を下記に変更

                o.color = v.color;
                vertInstancingColor(o.color);

SnapCrab_NoName_2019-3-5_3-46-51_No-00.png

これで、パーティクルも GPU Instancingが正常に行われた

SnapCrab_NoName_2019-3-5_3-51-59_No-00.png

もちろん、前回の方法で、ShadowCasterもGPU Instancing化された

今回できなかったやつ

本当はこのあたりもちゃんと調査したかったけど
案件が炎上したので、火消しに戻るため参照で

パーティクルのカスタムデータ

頂点属性をカスタマイズすることが出来ます

コンピュートシェーダでインスタンシングデータ作成

コンピュートシェーダでデータ作る

パーティクルのインスタンス事にプロパティ変更

マテリアル変数を UNITY_INSTANCING_BUFFER_START でブロック化し
インスタンス事に変数を与える方法は以前行ったが
これもパーティクルで行えるはずである

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2