Hello, it’s my first DevLog post with the intention of bringing some crazy experiments.

The GPU instancing allows you to draw many instances of the same mesh using an instanced shader in a single draw call, while still allowing a per-instance data set, including position, rotation and color, something that static batching does not allow.

gpuinstancing

Using GPU Instancing we have over 1900 saved by batching with hundreds of  dynamic objects of different colors. GPU Instancing is life!

When the CPU is the factor limiting your framerate, instancing can provide a significant performance benefit. To enable instancing on the Standard Shader, tick the Enable Instancing checkbox on the material settings. Alternatively, you can manually add instancing support to your own shaders.

Adding per-instance data

Even though the instanced GameObjects are sharing the same Mesh and Material, you can set Shader properties on a per-object basis using the MaterialPropertyBlock API. In the example below, each GameObject is assigned a random color value using the _Color property:

MaterialPropertyBlock props = new MaterialPropertyBlock();
MeshRenderer renderer;

foreach (GameObject obj in objects){
   float r = Random.Range(0.0f, 1.0f);
   float g = Random.Range(0.0f, 1.0f);
   float b = Random.Range(0.0f, 1.0f);
   props.SetColor("_Color", new Color(r, g, b));
   
   renderer = obj.GetComponent();
   renderer.SetPropertyBlock(props);
}

Adding instancing to your own shaders

The following example takes a simple unlit Shader and makes it capable of instancing:

Shader "InstancedShader"{
    Properties{
        _Color ("Color", Color) = (1, 1, 1, 1)
    }

    SubShader{
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #include "UnityCG.cginc"

            struct appdata{
                float4 vertex : POSITION;
                UNITY_INSTANCE_ID
            };

            struct v2f{
                float4 vertex : SV_POSITION;
                UNITY_INSTANCE_ID
            };

            UNITY_INSTANCING_CBUFFER_START (MyProperties)
            UNITY_DEFINE_INSTANCED_PROP (float4, _Color)
            UNITY_INSTANCING_CBUFFER_END
           
            v2f vert (appdata v){
                v2f o;

                UNITY_SETUP_INSTANCE_ID (v);
                UNITY_TRANSFER_INSTANCE_ID (v, o);

                o.vertex = UnityObjectToClipPos (v.vertex);
                return o;
            }
           
            fixed4 frag (v2f i) : SV_Target{
                UNITY_SETUP_INSTANCE_ID (i);
                return UNITY_ACCESS_INSTANCED_PROP (_Color);
            }
            ENDCG
        }
    }
}

The GPU instance feature is available from Unity 5.4.

Here’s an example with standard shader on my github.

See you next time.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s