Transition from Unity4 to Unity5, shader not functioning

HI,
I have a problem with custom made shader that worked perfectly in Unity4 but give strange result in Unity5.
Shader will normally produce an Xray kind of effect with circular shape when used with texture on a plane.

In Unity5 i will instead get elliptical shape, with dimensions being connected to the plane scale.
I havent wrote this shader myself, and my shader writting knowledge is basic, but i managed to find possible problem in unity documentation:

Non-uniform mesh scale has to be taken into account in shaders
In Unity 5.0, non-uniform meshes are not “prescaled” on the CPU anymore. This means that normal & tangent vectors can be non-normalized in the vertex shader. If you’re doing manual lighting calculations there, you’d have to normalize them. If you’re using Unity’s surface shaders, then all necessary code will be generated for you.

Im assuming that since my planes are scaled trough transform component, that this is making problems in Unity, heres the code to help with possible solution.

Shader "Custom/VisionShader" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _EffectX("X Coord", float) = 0.5
      _EffectY("Y Coord", float) = 0.5
      _EffectRadius("Effect Radius", float) = 4.0
      _ScaleX("X Scale", float) = 1.0
      _ScaleY("Y Scale", float) = 1.0
    }
    SubShader {
        Tags { "Queue" = "Transparent" }
      Pass {
   
         ZWrite Off
         Blend SrcAlpha OneMinusSrcAlpha
         Cull Off
         CGPROGRAM
         #pragma vertex vert
         #pragma fragment frag
          uniform sampler2D _MainTex;
          float _EffectX, _EffectY, dist, _EffectRadius, _ScaleX, _ScaleY;
          float4 designColor;
       
         struct vertexInput {
            float4 vertex : POSITION;
            float4 texcoord : TEXCOORD1;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float4 posInObjectCoords : TEXCOORD0;
            float4 tex : TEXCOORD1;
         };
         vertexOutput vert(vertexInput input)
         {
            vertexOutput output;
            output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
            output.posInObjectCoords = input.vertex;
         
            output.tex = input.texcoord;
            return output;
         }
         float4 frag(vertexOutput input) : COLOR
         {
             designColor = tex2D(_MainTex, float2(input.tex));
          
             dist = (input.posInObjectCoords.z - _EffectY) * (input.posInObjectCoords.z - _EffectY)  + (input.posInObjectCoords.x - _EffectX)*(input.posInObjectCoords.x - _EffectX) ;
        
            if (dist < _EffectRadius && _EffectRadius > 0)
            {
                if (designColor.a > (dist/_EffectRadius))
                {
                    designColor = float4(designColor.r, designColor.g , designColor.b, ((dist*dist/_EffectRadius)/_EffectRadius));
                }
            }
                    
            return designColor;
         }
         ENDCG
      }
   }
    Fallback "Diffuse"
  }

I looked for solution on internet and found that similar problem was solved using suggestion above to normalize vectors, changing

output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
to
output.pos = normalize(mul(UNITY_MATRIX_MVP, input.vertex));

but this didnt worked for me.
I have also put variables _ScaleX and _ScaleY that will hold scale of the transform component so that they can be used inside of shader.

Normalize takes a vector and makes it unit length. In other terms it’ll take any float3 and make its length 1. If you normalize the pos value (which is used to determine where to render it) it’ll just end up being some tiny sliver near the center of the scene, which is not what you want.

It seems like what you want is a circle with a world space radius that is offset from the center of the object, yes? Is there a reason to not just have the center of the circle defined in the world space position rather than some object relative offset?

If you change this line
output.posInObjectCoords= input.vertex;
to
output.posInObjectCoords= mul(_Object2World, input.vertex);

and change the _EffectX and _EffectY to world space that should work.

Alternatively you could try
output.posInObjectCoords = mul((float3x3)_Object2World, input.vertex.xyz).xyzz;

Which might just work if your object doesn’t have any rotation.

Thanks a lot for your efforts bgolus, but your solution didnt solved my problem, i got even stranger results such as instead of circle i would see a vertical bar type of shape. I wanted to clarify what im doing and what is the problem by giving graphic example of the issue, which might help you in understanding the problem.

So what im trying to do is to have this shader work on Unity5, since it works perfectly on Unity4. That means that for example if i have two Unity Plane meshes one behind each other, and in the image first plane is with black texture and plane behind it is with wooden crate texture, when i move mouse around VisionShader will make circular hole in the first texture. So i will be able to see trough the first plane and crates will be visible behind. Below left is unity4 image where shader is working as intended. On the other hand if i switch to unity5 i will instead get eliptical shape instead, look below right.

2306892--156056--Unity4Circle.png 2306892--156057--Unity5Elipse.png

So basically if you compare those two images below, you will come to conclusion that elipse has same proportion as the black box plane with transform components scale x = 2.9 y = 1 and Z = 1.2 (in this case because of plane oriantation z axis is what we usually think of y axes on the image above. Below is how that looks when compared one to the other.

2306892--156058--U4vsU5.png

So somewhere in mouse handling code i feed a data to shader _EffectX and _EffectY that are actually being a center position of circle where mouse is currently positioned and _EffectRadius is current radius of the circle. _ScaleX and _ScaleY are there just for possible solution of this problem.
Let me know if you need any further clarification and if all of this makes sense?

A couple of random things. You shouldn’t define variables outside of a struct or function unless they’re the ones coming from the material, so dist and designColor have been moved to inside of the frag function. You’re on the right path with passing the scale, all you really need to do is multiply the posInObjectCoords by those values properly. You were passing a full float4 of the object position when you only care about 2 of those dimensions so the below shader only passes the two you want (and scales them) in the vert function.

Shader "Custom/VisionShader" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _EffectX("X Coord", float) = 0.5
      _EffectY("Y Coord", float) = 0.5
      _EffectRadius("Effect Radius", float) = 4.0
      _ScaleX("X Scale", float) = 1.0
      _ScaleY("Y Scale", float) = 1.0
    }
    SubShader {
        Tags { "Queue" = "Transparent" }
      Pass {
  
         ZWrite Off
         Blend SrcAlpha OneMinusSrcAlpha
         Cull Off
         CGPROGRAM
         #pragma vertex vert
         #pragma fragment frag
          uniform sampler2D _MainTex;
          float _EffectX, _EffectY, _EffectRadius, _ScaleX, _ScaleY;
      
         struct vertexInput {
            float4 vertex : POSITION;
            float4 texcoord : TEXCOORD1;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float2 posInObjectCoords : TEXCOORD0;
            float4 tex : TEXCOORD1;
         };
         vertexOutput vert(vertexInput input)
         {
            vertexOutput output;
            output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
            output.posInObjectCoords = input.vertex.xz * float2(_ScaleX, _ScaleY);
        
            output.tex = input.texcoord;
            return output;
         }
         float4 frag(vertexOutput input) : COLOR
         {
            float4 designColor = tex2D(_MainTex, float2(input.tex));
            float2 offset = input.posInObjectCoords - float2(_EffectX, _EffectY);
            float dist = dot(offset, offset);
      
            if (dist < _EffectRadius && _EffectRadius > 0)
            {
                if (designColor.a > (dist/_EffectRadius))
                {
                    designColor = float4(designColor.rgb, ((dist*dist/_EffectRadius)/_EffectRadius));
                }
            }
                  
            return designColor;
         }
         ENDCG
      }
   }
    Fallback "Diffuse"
  }

Lastly there’s a change in the dist calculation. You were doing all but the last step of the right angle triangle / pythagorean theorem calculation in long hand form (writing out each value and subtraction individually). That’s fine, but the shader above now does the same with built in functions so it’s slightly faster. It’s a cheap enough shader that it likely doesn’t matter either way, but I changed it anyway.

Really the value you have in dist in both your shader and mine is the distance squared and not the distance but I didn’t want to change how the shader functions.

You can change:
float2 offset = input.posInObjectCoords - float2(_EffectX, _EffectY);
float dist = dot(offset, offset);
to
float dist = length(input.posInObjectCoords - float2(_EffectX, _EffectY));
And now it’s the actual distance, but that’ll mean _EffectRadius won’t act the same anymore, and the falloff won’t quite be the same so
designColor = float4(designColor.rgb, ((dist*dist/_EffectRadius)/_EffectRadius));
will have to be
designColor = float4(designColor.rgb, ((pow(dist,4)/_EffectRadius)/_EffectRadius));
to get the same falloff.

Thanks for all explanations and code corrections, I also found one line that i copied wrong in original code and that didnt want to compile, so i changed
float4 designColor = tex2D(_MainTex, float2(input.tex));
to
float4 designColor = tex2D(_MainTex, float2(input.tex.xy));
and then i was able to use shader.

Unfortunately nothing seems to be changed after implementing your code, i still get elliptical shape, which makes me wonder if frag functions should be also/instead changed to include scale?

Are you setting _ScaleX and _ScaleY to 2.9 and 1.2?

Oh man that did it!, the script that was feeding that info was not attached to the object, i moved code to another script and now it works like charm!

I dont know if I can thank you enough cause this really saved my day, but im glad there is people like you that spend their time helping other folks.

Im just putting the working script here, in case anyone would like to use it.

Shader "Custom/VisionShader" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _EffectX("X Coord", float) = 0.5
      _EffectY("Y Coord", float) = 0.5
      _EffectRadius("Effect Radius", float) = 4.0
      _ScaleX("X Scale", float) = 1
      _ScaleY("Y Scale", float) = 1
    }
    SubShader {
        Tags { "Queue" = "Transparent" }
      Pass {
         ZWrite Off
         Blend SrcAlpha OneMinusSrcAlpha
         Cull Off
         CGPROGRAM
         #pragma vertex vert
         #pragma fragment frag
          uniform sampler2D _MainTex;
          float _EffectX, _EffectY, _EffectRadius, _ScaleX, _ScaleY;
   
         struct vertexInput {
            float4 vertex : POSITION;
            float4 texcoord : TEXCOORD1;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float2 posInObjectCoords : TEXCOORD0;
            float4 tex : TEXCOORD1;
         };
         vertexOutput vert(vertexInput input)
         {
            vertexOutput output;
            output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
            output.posInObjectCoords = input.vertex.xz * float2(_ScaleX, _ScaleY);
     
            output.tex = input.texcoord;
            return output;
         }
         float4 frag(vertexOutput input) : COLOR
         {
            float4 designColor = tex2D(_MainTex, float2(input.tex.xy));
            float2 offset = input.posInObjectCoords - float2(_EffectX, _EffectY);
            float dist = dot(offset, offset);
   
            if (dist < _EffectRadius && _EffectRadius > 0)
            {
                if (designColor.a > (dist/_EffectRadius))
                {
                    designColor = float4(designColor.rgb, ((dist*dist/_EffectRadius)/_EffectRadius));
                }
            }
            return designColor;
         }
         ENDCG
      }
   }
    Fallback "Diffuse"
}

And i will experiment with distance and use your code also just to see where it gets me.
Big thanks!