Flag Shader waving differently in VR using Headset

Hi, the following is the shader I am using to get flag flying effect. And I have issue with my shader. If more than one object of same material is present, then my flag isn’t flying. The following video below shows this.
What I understand is it has something to do with Depth buffer. If I put “Queue” = “Transparent”, two flags of same material are flying if they are at same depth from camera. But I am not able to know what’s happening here.

If I write the same Pass present in my shader two times, now all fly correctly. Why is it so? How to make it independent of number of objects of same material in camera view?

Thanks in advance :slight_smile:

My shader code with one pass

Shader "Custom/latestFlagShader" {
    Properties {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Scale ("Scale", float) = 1.0
        _Speed ("Speed", float) = 1.0
        _Frequency ("Frequency", float) = 1 
    }

    SubShader {
        Tags { "RenderType"="Opaque" }
        
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float _Scale;
            float _Speed;
            float _Frequency;
            float _Brightness;

            v2f vert (appdata v)
            {
                v2f o;
                float value =  _Scale * sin(_Speed*_Time.z + ((v.uv.x + 0.1) *5*_Frequency));
                v.vertex.xyz += value * v.normal;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

Are you sure this isn’t an occlusion issue? The shader is pretty tame, I don’t think that’s the problem. I’ve done sin movement in VR more or less the same as this and it worked fine.

Hi, Thanks for the reply. But it’s not occlusion issue, I turned off all occlusion related things but still problem exists. And I was wrong, it’s happening even when VR is not enabled too.

Actually if more than one object of same material is present, then my flag isn’t flying. The following video in URL shows this.
What I understand is it has something to do with Depth buffer. If I put “Queue” = “Transparent”, two flags of same material are flying if they are at same depth from camera. But I am not able to know what’s happening here.

If I write the same Pass present in my shader two times, now all fly correctly. Why is it so? How to make it independent of number of objects of same material in camera view?

This is caused by dynamic batching.

You’re offsetting the local position of the vertices by the normal. On an unscaled mesh this would all work fine, and the batched and non-batched results would be the same. However you’re scaling those meshes up.

Basically Unity does static and dynamic batching. This takes any mesh using the same material and combines them into one large mesh with it’s pivot at world space 0,0,0. It also normalizes the normals in the batched mesh. In the scene view (which doesn’t do batching) and with a single mesh it’ll offset the mesh via the normal (which will have a length of one), then apply the mesh’s scaling making the offset appear larger. On a batched mesh it’ll do the same thing, but the mesh is prescaled, so the scale is now 1 and doesn’t get any bigger.

Change this one line in your shader:

v.vertex.xyz += value * normalize(v.normal);

Then increase the Scale on the material to be as wanted. Alternatively you can disable batching in your project (not advised) or on that shader using the tag "DisableBatching"="True"

Thankyou very much … saved my day !! :slight_smile:

Hi, changing the line (adding normalize()) you mentioned solved the problem partially but not completely. They are flying with a bit more amplitude than previous, but they are not flying in the game view with the same amplitude as in scene view.

“DisableBatching” = “True” is working prefectly fine. But is it not possible to have batching, and make this shader work correctly?

You can see this in the following video:

Because I was being a bit of an idiot when I last replied. That one line change isn’t enough.

Try this:

                float value =  _Scale * sin(_Speed*_Time.z + ((v.uv.x + 0.1) *5*_Frequency));
                float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                worldPos.xyz += value * worldNormal;
                o.vertex = mul(UNITY_MATRIX_VP, worldPos);

Thankyou very much, it’s working :slight_smile: .I need to do w.r.to world space because batching changes local space values?

Correct.

Okay… thankyou :slight_smile: