Quick answer: Apply uv.y = lerp(uv.y, 1 - uv.y, step(0, _ProjectionParams.x)) in a Custom Function, or simpler: multiply Y by _ProjectionParams.x when sampling a screen-relative texture. Vulkan flips Y vs Metal/GL.
Custom shader uses Screen Position to sample a render texture. Looks correct on PC. Same shader on Android Vulkan shows a vertical flip. ProjectionParams.x covers it.
The Symptom
Screen-relative sampling (refraction, distortion, screen-grab) renders flipped on Android Vulkan. Same shader on Metal or DirectX is correct.
The Fix
In a Custom Function node:
void SafeScreenUV_float(float2 ScreenUV, out float2 Out)
{
Out = ScreenUV;
#if UNITY_UV_STARTS_AT_TOP
Out.y = 1.0 - Out.y;
#endif
}
UNITY_UV_STARTS_AT_TOP is defined on platforms with flipped framebuffer-Y. Branch and flip.
Or use ProjectionParams.x directly:
float2 uv = ScreenUV;
if (_ProjectionParams.x < 0) uv.y = 1.0 - uv.y;
Screen Position Modes
- Default: NDC, divided by W. For texture sampling.
- Raw: Pre-divide. For math.
- Center: Centered around 0,0.
- Tiled: Wraps to [0,1].
- Pixel: Screen pixel coords.
For sampling _CameraOpaqueTexture or similar, use Default and apply the platform flip.
Verifying
Build to Android Vulkan device. The screen-relative effect should match the Editor and PC builds. If still flipped, the platform branch isn’t firing — check that the include is reaching the shader.
“ProjectionParams.x or UNITY_UV_STARTS_AT_TOP. Vulkan stops flipping.”
Related Issues
For SRP Batcher, see SRP Batcher. For Shader Graph not in build, see build shader updates.
Branch the flip. Vulkan reads upright.