How to make GPU Instancing with different textures via texture atlas?

Hi.
Basicly, i have a decal shader that i use on GPU instancing with DrawnMeshInstanced.
And i want to make them randomly select texture from texture atlas, by chaning UV like (0,0) (0,0.5f) etc.

I planed to change their UV based on world position is even or not, because decals don’t move. However, this randomized system doesn’t work. Because when one of the decal is changed all of the decals are change to same texture, instead of that one who moves.

The code

float3 baseWorldPos = mul(unity_ObjectToWorld , float4(0,0,0,1)).xyz;

                float2 _randomUV = float2(0, 0);
               
                if (_Random == 1) {
                    float compareValue = int(abs(baseWorldPos.x));
                    if (getMod(compareValue, 2) == 0) {
                        _randomUV = float2(0, 0);

                    }
                    else {
                        _randomUV = float2(0.5f,0);
                    }

                }
   

               
                float4 tex;
                tex = tex2D(_MainTex, i.texcoord + _randomUV);
                ...


Only the right one should have changed but the left one changed too.

When i disable the GPU instancing on material everthing works fine. But i need to open it so i can use this on DrawMesh funciton.
I don’t know the problem is the getting world position of the object, or the _randomUV is shared on every decal instead of calculated on each one.

Can you show your full shader code?

I suspect the issue is you’re not passing the instance ID from the vertex shader to the fragment shader, so the unity_ObjectToWorld in the fragment shader is always the one for the first instance. You need to use the appropriate macros to pass the value and initialize it in the fragment shader.

See the “Vertex and fragment shader example” on this page:

Yep, this is the whole code. I added “UNITY_SETUP_INSTANCE_ID(i);” on frag_mult just now, it wasn’t there before.
But no changes, i tried to move it after the baseWorldPos calculated but still no changes.

Shader "Alde/OverlayBlend"
{
    Properties
    {
        _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
        _Color("Color", Color) = (1,1,1,1)
        _overlayType("Test", Int) = 3
        _emmison("Emmision", Float) = 1
        [MaterialToggle] _Random("Use Random Texture", Float) = 0
        _IntersectionThresholdMax("Intersection Threshold Max", float) = 1

    }

        SubShader
        {
            Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
           
            ZWrite Off
            Lighting Off
            Cull Off

            LOD 100

            Pass
            {

            AlphaToMask On
           
            BlendOp [_overlayType]
           
            Blend SrcAlpha OneMinusSrcAlpha
            Blend DstColor SrcColor


            CGPROGRAM
            #pragma vertex vert_vct
            #pragma fragment frag_mult
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma multi_compile_fog
            #pragma multi_compile_instancing

            #pragma instancing_options nolightprobe nolightmap nolodfade //procedural:setup
            #include "UnityCG.cginc"

           

            sampler2D _CameraDepthTexture;
            sampler2D _MainTex;
            float4 _MainTex_ST;
           
            float _Random;
            UNITY_INSTANCING_BUFFER_START(Props)
                UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
                UNITY_DEFINE_INSTANCED_PROP(float, _overlayType)
                UNITY_DEFINE_INSTANCED_PROP(float, _emmison)
                UNITY_DEFINE_INSTANCED_PROP(float, _IntersectionThresholdMax)
                UNITY_DEFINE_INSTANCED_PROP(half3, _WorldPos)
            UNITY_INSTANCING_BUFFER_END(Props)



            struct vin_vct
            {
                float4 vertex : POSITION;
                float4 color : COLOR;
                float2 texcoord : TEXCOORD0;
                float3 normal : NORMAL;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float4 scrPos : TEXCOORD0;
                half2 texcoord : TEXCOORD1;
                UNITY_FOG_COORDS(2)
                float3 normal : NORMAL;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            v2f vert_vct(vin_vct v)
            {
                v2f o;
                UNITY_TRANSFER_INSTANCE_ID(v, o);
                UNITY_INITIALIZE_OUTPUT(v2f, o);
                UNITY_SETUP_INSTANCE_ID(v);

                o.vertex = UnityObjectToClipPos(v.vertex);
                o.color = v.color;
                o.scrPos = ComputeScreenPos(o.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);

                UNITY_TRANSFER_FOG(o, o.vertex);
                return o;
            }
           
            float getMod(float val, float bol) {
                return val - (bol * floor(val / bol));
            }

            float4 frag_mult(v2f i) : COLOR
            {
                UNITY_SETUP_INSTANCE_ID(i);
                float3 baseWorldPos = mul(unity_ObjectToWorld , float4(0,0,0,1)).xyz;
               
                float2 _randomUV = float2(0, 0);
               
                if (_Random == 1) {
                    float compareValue = int(abs(baseWorldPos.x));
                    if (getMod(compareValue, 2) == 0) {
                        _randomUV = float2(0, 0);

                    }
                    else {
                        _randomUV = float2(0.5f,0);
                    }

                }
   
                float4 tex;
                tex = tex2D(_MainTex, i.texcoord + _randomUV);

                tex *= UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
                float4 final = tex;
                final.a = i.color.a * tex.a;

                if (tex.r == i.color.r && tex.g == i.color.g && tex.b == i.color.b) {
                    final.rgb = i.color.rgb * tex.rgb * 0;
                }
                else {
                    final.rgb = i.color.rgb * tex.rgb * 2;
                }
                float4 last = lerp(float4(0.5f, 0.5f, 0.5f, 0.5f), final, final.a)
                    * UNITY_ACCESS_INSTANCED_PROP(Props, _emmison);


               
                if (tex.a < 0.6f) {
                    last.a = 0;
                }
               
                //dissolve when no place behind
                float3 viewDir = _WorldSpaceCameraPos.xyz - baseWorldPos;
                float Rim = max(0.0, 1 - saturate(dot(i.normal, normalize(viewDir)))) +0.5f;

                float depth = LinearEyeDepth(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.scrPos)));
                float diff = saturate(UNITY_ACCESS_INSTANCED_PROP(Props, _IntersectionThresholdMax)
                    * (depth - i.scrPos.w) * Rim);

                fixed4 col = lerp(last, float4(1, 1, 1, 0), diff * diff * diff * (diff * (6 * diff - 15) + 10));

                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;

            }

            ENDCG

        }


        }

}