iOS image effect trouble

I’m trying to write some image effects for iOS, and I figured the simplest test case would be the best starting point. The following effect script and shader work fine in the editor (no visible effect), but just result in a black screen on an iPad. As far as I can tell, this is the way you’re supposed to write image effects, and using the shader on regular geometry works just fine. Can anyone spot any problems?

using UnityEngine;

[ExecuteInEditMode]
public class PassthroughEffect : ImageEffectBase {
	
	protected void OnRenderImage(
		RenderTexture source,
		RenderTexture destination
	) {
		Graphics.Blit(source, destination, material);
	}
}
Shader "Hidden/Passthrough" {
	Properties {
		_MainTex ("Render Input", 2D) = "white" {}
	}
	SubShader {
		
		Pass {
			CGPROGRAM
				#pragma vertex vert_img
				#pragma fragment frag
				#include "UnityCG.cginc"
			
				sampler2D _MainTex;
			
				float4 frag(v2f_img IN) : COLOR {
					half4 c = tex2D (_MainTex, IN.uv);
					return c;
				}
			ENDCG
		}
	}
}

I found the issue. UnityCG’s vert_img calls MultiplyUV(), which looks like this:

float2 MultiplyUV (float4x4 mat, float2 inUV) {
	float4 temp = float4 (inUV.x, inUV.y, 0, 0);
	temp = mul (mat, temp);
	return temp.xy;
}

Replacing that call with the following appears to make everything work as expected on both desktop and iOS:

o.uv = v.texcoord;

I guess maybe UNITY_MATRIX_TEXTURE0 isn’t properly populated on iOS? I don’t really know what I’d be missing by skipping that multiplication.

I’m pretty sure this is related to the fact that mobiles use OpenGL ES which either runs in pure fixed function or in pure shader driven and in the later case, OpenGL will not fill the ‘fixed function registers’ as there is no predefined vertex pipeline to feed it anymore. As such you have to provide the pixel shader with the data it needs in the vertex shader or it will not be present (unless its one of the default input structures unity offers)

Question is why it should impact an inbuilt function as they are meant to handle this kind of stuff properly. Sounds like something else or even more is involved here.

Mind if I request that you report it as a bug so it can officially be looked into?

Yup, it’s reported.

The shader works fine on actual geometry, so I assume it’s just that Unity isn’t filling in UNITY_MATRIX_TEXTURE0 when rendering image effects on an actual iOS device.

A developer got back to me and explained that I need this set of fixed function commands for image effects:

ZTest Always Cull Off ZWrite Off Fog { Mode Off }

Sure enough, all my image effects work using vert_img after adding that line. I tried with each command individually, and ZTest Always seems to work on its own–perhaps the issue is some peculiarity of the PowerVR deferred renderer. However, it’s probably best to use the whole line verbatim.

Thanks for sharing this