One shader function written different ways gives different results. (Unity 2017)

265 Views Asked by At

In our project on Unity 2017 we use our own PixelSnap function instead of UnityPixelSnap.

Recently we found that some fullscreen sprites have size on screen some less than the screen on some resolutions.
Here is our function with all return cases that I tried

#include "UnityCG.cginc"

float4 _UnityPixelSnap(float4 coord)
{
    //[1]
    return float4(floor((coord.xy * 0.5f + 0.5f ) * _ScreenParams.xy) * (_ScreenParams.zw - 1.0f) * 2.0f - 1.0f, coord.z, coord.w);
    //[2]
    return float4(floor((coord.xy * 0.5f + 0.5f ) * _ScreenParams.xy) / (_ScreenParams.xy) * 2.0f - 1.0f, coord.z, coord.w);
    //[3]
    return float4(floor((coord.xy * 0.5f) * _ScreenParams.xy) / (_ScreenParams.xy) * 2.0f, coord.z, coord.w);
    //[4]
    return float4(round((coord.xy * 0.5f) * _ScreenParams.xy) / (_ScreenParams.xy) * 2.0f, coord.z, coord.w);
}

In the next example, normally, right border of screen must be totally black.
Case 1,2 and 3 gives us vertical pixel line (picture)
But case 4 gives normal results. If you will try to plot these functions, for example, in Matlab, for any _ScreenParams and array coord.xy (-1,1) with any step, you will see absolutely same graphics.

And please, don't ask me why we use Unity 2017 and use our own PixelSnap. I am new in this project and I need to discover this issue.
Thanks everybody!

Here is UnityCG.cginc UnityPixelSnap function for comparasion:

inline float4 UnityPixelSnap (float4 pos)
{
    float2 hpc = _ScreenParams.xy * 0.5f;
#if  SHADER_API_PSSL
// sdk 4.5 splits round into v_floor_f32(x+0.5) ... sdk 5.0 uses v_rndne_f32, for compatabilty we use the 4.5 version
    float2 temp = ((pos.xy / pos.w) * hpc) + float2(0.5f,0.5f);
    float2 pixelPos = float2(__v_floor_f32(temp.x), __v_floor_f32(temp.y));
#else
    float2 pixelPos = round ((pos.xy / pos.w) * hpc);
#endif
    pos.xy = pixelPos / hpc * pos.w;
    return pos;
}

››

0

There are 0 best solutions below