Refraction Surface Shader Upside down

Hello everyone,

I have a surface refraction shader which works great when my camera is set to deferred lighting. Weirdly enough though, as soon as I switch to forward rendering, the shader refracts the things behind it upside down. I don’t know much about shaders, but I’m pretty sure it has something to do with the “Render Texture Coordinates” section in this post.

Here is the shader:

Shader "Effects/Distort" {
		_Refraction("Refraction", Range(0.00, 100.0)) = 1.0
		_DistortTex("Base (RGB)", 2D) = "white" {}
		_ObjectVisibility("Visibility", Range(0.00, 1.00)) = 0.05


		Tags{ "RenderType" = "Transparent" "Queue" = "Overlay" }
		LOD 100



#pragma surface surf NoLighting
#pragma vertex vert

		fixed4 LightingNoLighting(SurfaceOutput s, fixed3 lightDir, fixed atten) {
		fixed4 c;
		c.rgb = s.Albedo;
		c.a = s.Alpha;
		return c;

	sampler2D _GrabTexture : register(s0);
	sampler2D _DistortTex : register(s2);
	float _Refraction;

	float _ObjectVisibility;

	float4 _GrabTexture_TexelSize;

	struct Input {
		float2 uv_DistortTex;
		float3 color;
		float3 worldRefl;
		float4 screenPos;
	struct appdata_t {
		float4 vertex : POSITION;

	void vert(inout appdata_full v, out Input o) {
		o.color = v.color;

	void surf(Input IN, inout SurfaceOutput o) {
		float3 distort = tex2D(_DistortTex, IN.uv_DistortTex) * float3(IN.color.r,IN.color.g,IN.color.b);
		float2 offset = distort * _Refraction * _GrabTexture_TexelSize.xy;
		IN.screenPos.xy = offset * IN.screenPos.z + IN.screenPos.xy;
		float4 refrColor = tex2Dproj(_GrabTexture, IN.screenPos);
		o.Alpha = refrColor.a;
		o.Emission = refrColor.rgb * (1+_ObjectVisibility);

The previously linked post talks about inserting the following snippet somewhere:

if (_MainTex_TexelSize.y < 0)
        uv.y = 1-uv.y;

I probably have to change _MainTex_TexelSize to _GrabTexture_TexelSize, but that’s pretty muc all I know. Where do I need to insert this snippet to get it working?

Thanks for your help in advance!

If you are using iOS, then that method won’t work (I guess)
So here is a solution documented on the link that using ComputeGrabScreenPos function.

In the vertex shader vert, you must get a pos_refraction by defining it in Input structure and doing this:

o.vertex = UnityObjectToClipPos(v.vertex);
o.pos_refraction = ComputeGrabScreenPos(o.vertex);

Then in the surf function, you can grab your texture by doing this:

fixed3 refractColor = tex2Dproj(_GrabTexture, IN.pos_refraction);

The reason why it’s better to have an extra variable is that if you have a depth for your shader, its position info shouldn’t be gotten from ComputeGrabScreenPos, instead, it should be from ComputeScreenPos. It’s tricky if you don’t know this, otherwise, it’s like when you got your refraction right, you depth wouldn’t work. If you keep the depth, your refraction is still upside down.
Overall, It costed couple hours to actually get what I expect. Hopefully, this is also working for you.