unity_InstanceID always 0 in URP?

I’m probably doing something wrong, but I’m using the
DrawMeshInstancedIndirect with MonoBehaviour example verbatim from the docs:

with this shader:

Shader "Unlit/InstancedTest"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #pragma instancing_options procedural:setup
            #pragma target 4.5

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;           
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = v.vertex;
                o.color = fixed4(0,1,0,1);;

#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
                o.vertex += float4(-unity_InstanceID.xxx, 0);
                o.color = fixed4(1,0,unity_InstanceID*0.25,1);
#endif
                o.vertex = UnityObjectToClipPos(o.vertex);
                return o;
            }

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

What I would expect to see is my instanced mesh ( a sphere) offset in space and color for each instance. Instead, all I see is 1 red sphere. It’s red, which means that
UNITY_PROCEDURAL_INSTANCING_ENABLED is defined, otherwise it would be green. I’m guessing

  • all the instances have id 0 are drawing on top of each other
  • or there is only one instance being drawn.
    Any thoughts on what I’m missing or if this won’t work in URP?

edit:
since UNITY_VERTEX_INPUT_INSTANCE_ID I also tried this, but same result, single red mesh

#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
o.vertex += float4(-v.instanceID.xxx, 0);
o.color = fixed4(1,0,v.instanceID*0.25,1);
#endif
2 Likes

I’ve been able to reproduce in Classic renderer as well. However, using explicit SV_InstanceID does work for Classic and URP.

Shader "Unlit/InstancedTest"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            struct appdata
            {
                float4 vertex : POSITION;
                uint instanceID : SV_InstanceID;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;         
            };

            v2f vert (appdata v)
            {
                float3 worldPosition = v.vertex.xyz + float4(v.instanceID.xxx, 0);
                fixed4 color =  fixed4(1,0,v.instanceID*0.01,1);

                v2f o;
                o.vertex = mul(UNITY_MATRIX_VP, float4(worldPosition, 1.0f));
                o.color = color;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = i.color;
                return col;
            }
            ENDCG
        }
    }
}
3 Likes

Wow, I’ve been trying to find a solution for this problem for hours. This is the one post I found that actually gets me access to the instance ID and all I had to do was include it in the appdata struct … crazy …

2 Likes

Hi! This remains broken. The docs occasionally mention the existence of unity_InstanceID but never show how it’s used. Can this be fixed, or the docs improved?