Fragment shader Image effect horizontally flipped in Editor

Pretty new to shaders so bear with me, messing with a fragment shader Image Effect that stretches the left and right side of the screen. Shader displaces fragments positively in the x axis based on an input textures red value and negatively by green.

However I seem to have a weird issue wherein the effect is flipped horizontally in editor, that is, it displaces positively in the green and negatively in the red. For example if I comment out one sides effect (for example positive displacement) then the editor will show the effect on the right side of the screen, whereas any build (WebGL, standalone, android etc) will show the effect on the left of screen. Naturally I can work around it by simply taking this into account, but I’d really like to understand what is happening. Does Unity Editor for some reason read textures right to left? Or does it read colour values GRBA? I can’t seem to find any information on horizontal flipping, only tons of vertical from variations between DX and OpenGL, which isn’t the case here because building to both behaves the same.

For what it’s worth the effect seems much cruder in any build than it does in editor, so any better ways of accomplishing this or information on how Unity handles shaders differently would be ideal.

Shader "Hidden/EdgeStretch"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _DisplacementTex("Displacement Texture", 2D) = "white" {}

        _DisplacementValue("Displacement Coefficient", Range(0.0, 1.0)) = 1.0
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
         
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            sampler2D _DisplacementTex;
            float _DisplacementValue;

            v2f vert (appdata v)
            {
             
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = v.uv;

                if (_ProjectionParams.x < 0)
                    o.uv[1] = 1 - o.uv[1];

                return o;
            }
         
         

            fixed4 frag (v2f i) : SV_Target
            {
                //Grab Red Green values from displacement texture
                fixed2 value = tex2D(_DisplacementTex, i.uv);
                fixed2 modified = value / 3;

                //Modify the co-ordinate and clamp it between 0 and 1
                //Displace positively by red and negatively by green on X axis
                i.uv[0] -= modified[0] * _DisplacementValue;
                i.uv[0] += modified[1] * _DisplacementValue / 2;
                i.uv = saturate(i.uv);

                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

Hello,

It is difficult for me to debug this without having the effect in front of me.
You should take a look at post-processes displacements shaders in the Effects Unity Package, it may certainly help you.

About this code in your vertex shader, you should not check the y axis instead of the x axis of _ProjectionParams ?

if (_ProjectionParams.x < 0)
o.uv[1] = 1 - o.uv[1];

Maybe you need to use the UNITY_UV_STARTS_AT_TOP macro ?

That code specifically comes from Unity Docs in dealing with the differences in the way openGL and DirectX handle texture vertical coordinates. I played with it to try and handle the x coord too but it didn’t do anything but break the shader.

Imgur: The magic of the Internet This is a very basic idea of what it’s doing. This is without any displacement value

Imgur: The magic of the Internet And this is displacement of 0.2

Imgur: The magic of the Internet The displacement Texture

The issue is as you can see, the right is more displaced than the left (as one sides displacement is halved). This will be the left side in this instance in any platform I build to (whether that be Android, windows standalone or WebGL) because for some bizarre reason the effect is horizontally flipped. I’d love to figure out why but I’m absolutely stumped

I don’t really know why your effect is flipped horizontally but have a look at this: Handling Texture Tiling and Offset in a Unity3d Vertex and Fragment Shader using TRANSFORM_TEX macro

How I would have done it: (NOT TESTED)

fixed4 frag (v2f i) : SV_Target
{
   // Using a gray texture, black is -1, middle grey is 0, white is 1
   float offset = tex2D(_DisplacementTex, i.uv).r;
   offset = (offset * 2) -1 // Convert to range -1 to 1
   //float modified = value / 3; //why divide by 3 ?

   i.uv.x += offset * _DisplacementValue;

   //i.uv = saturate(i.uv); why clamp ?

   fixed4 col = tex2D(_MainTex, i.uv);
   return col;
}

I just ended up finding out that for some reason, Unity in builds doesn’t Serialize any assigned textures to a shader? A major issue I came across was it was assigning who knows what to the _DisplacementTex whenever you build, overcome by assigning the Texture within the CameraComponent and assigning it to the cameras material that way. Not even sure why they would bother allowing values to be assigned to a shader if they get discarded on build anyway.

Some of the questions you had related to just values I had been tweaking to get the shader looking better (such as that wonderful magic number 3)

Cheers for the help

I don’t think Unity will keep a texture assigned to a shader as a default value in build but a material will keep the reference to your texture anyway.

If you use it as a post-process, you can see in Unity post-effects that there is always a .cs scripts assigning values to the shader through c# serialization.