GPU instancing not working with 'Legacy Shaders/VertexLit' shader.

I have various meshes with the same material, which uses the ‘Legacy Shaders/VertexLit’ shader, this material has GPU instancing enabled, but for some reason it doesn’t batch the meshes in the Frame Debugger, every mesh is drawn separately, so I have a lot of draw calls.

What’s weird, is that when I set this same material to use the ‘Standard’ shader, it starts working, and batches all the meshes correctly in a single draw call.

Does anyone know why this happens? And how to make it work with the ‘Legacy Shaders/VertexLit’ shader?

have you solved it?

as far as i can tell, this shader doesn’t support gpu instancing~ denoted in shaders by
#pragma multi_compile_instancing

i’ve added the functionality to my own shaders and it’s quite simple.

the vertex lit shader
Unity-Built-in-Shaders/DefaultResourcesExtra/Normal-VertexLit.shader at master · TwoTailsGames/Unity-Built-in-Shaders · GitHub

the standard shader (which has it)
Unity-Built-in-Shaders/DefaultResourcesExtra/Standard.shader at master · TwoTailsGames/Unity-Built-in-Shaders · GitHub

how to add
Rendering 19 (catlikecoding.com)

1 Like

if you dont mind, could you please give me a specific example on how gpu instancing is implemented on that shader? Im in very need of it.

the last link i sent has a very detailed explanation.

i think it’s about 5 lines in the shader.

1 Like

Is there something im missing here?

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

// Unlit shader. Simplest possible textured shader.
// - SUPPORTS lightmap
// - no lighting
// - no per-material color

Shader "Heya" {

Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
}

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

    // Non-lightmapped
    Pass {
        Tags { "LightMode" = "Vertex" }
        Lighting Off
        SetTexture [_MainTex] {
            constantColor (1,1,1,1)
            combine texture, constant // UNITY_OPAQUE_ALPHA_FFP
        }
    }

    // Lightmapped
    Pass
    {
        Tags{ "LIGHTMODE" = "VertexLM" "RenderType" = "Opaque" }

        CGPROGRAM

        #pragma vertex vert
        #pragma fragment frag
        #pragma target 2.0
        #include "UnityCG.cginc"
        #pragma multi_compile_fog
        #pragma multi_compile_instancing
        #define USING_FOG (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))

        // uniforms
        float4 _MainTex_ST;

        // vertex shader input data
        struct appdata
        {
            float3 pos : POSITION;
            float3 uv1 : TEXCOORD1;
            float3 uv0 : TEXCOORD0;
            UNITY_VERTEX_INPUT_INSTANCE_ID
        };

        // vertex-to-fragment interpolators
        struct v2f
        {
            float2 uv0 : TEXCOORD0;
            float2 uv1 : TEXCOORD1;
#if USING_FOG
            fixed fog : TEXCOORD2;
#endif
            float4 pos : SV_POSITION;
            UNITY_VERTEX_OUTPUT_STEREO
        };

        // vertex shader
        v2f vert(appdata IN)
        {
            v2f o;
            UNITY_SETUP_INSTANCE_ID(IN);
            UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

            // compute texture coordinates
            o.uv0 = IN.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
            o.uv1 = IN.uv0.xy * _MainTex_ST.xy + _MainTex_ST.zw;

            // fog
#if USING_FOG
            float3 eyePos = UnityObjectToViewPos(float4(IN.pos, 1));
            float fogCoord = length(eyePos.xyz);  // radial fog distance
            UNITY_CALC_FOG_FACTOR_RAW(fogCoord);
            o.fog = saturate(unityFogFactor);
#endif

            // transform position
            o.pos = UnityObjectToClipPos(IN.pos);
            return o;
        }

        // textures
        sampler2D _MainTex;

        // fragment shader
        fixed4 frag(v2f IN) : SV_Target
        {
            fixed4 col, tex;

            // Fetch lightmap
            half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.uv0.xy);
            col.rgb = DecodeLightmap(bakedColorTex);

            // Fetch color texture
            tex = tex2D(_MainTex, IN.uv1.xy);
            col.rgb = tex.rgb * col.rgb;
            col.a = 1;

            // fog
    #if USING_FOG
            col.rgb = lerp(unity_FogColor.rgb, col.rgb, IN.fog);
    #endif
            return col;
        }

        ENDCG
    }
}
}

looks correct to me! just test it by duplicating an object and enabling instancing :slight_smile:

1 Like

it does not work, I took around 60 objects, no dynamic and static batching, and just gpu instancing enabled, Clicked on play button, and there are 65 drawcalls and saved 0. Im completely disappointed for two days, where switching to Mobile/diffuse shader at the same time shows me Gpu instancing working i mean 1 drawcall and saved 63. Idk what’s wrong in my shader

i didn’t even notice earlier, but you have two passes in the shader! that would be why.

add the instancing to the first pass as well and i believe that should fix your problem

I removed the first pass after having the objects lightmapped, gpu instancing doesnt work somehow. Whatever, Thank you a lot, I will not use gpu instancing

1 Like