Search Unity

Question ComputeGrabScreenPos not including all layers?

Discussion in 'Shaders' started by Pattrigue, Sep 28, 2022.

  1. Pattrigue

    Pattrigue

    Joined:
    Nov 24, 2018
    Posts:
    67
    Hi,

    I'm trying to make a distortion effect, and I got it working well.
    But for some reason, the effect does not apply to all sprites on layers below, as seen in the clip below:


    The red star sprite is on the Sorting Layer behind the white sprite with the shader.
    What's weird is that it works fine if the "Order in Layer" property is set to 0 or less for the red star sprite.

    Furthermore, it only happens in this specific part of the level. It works fine later on in the level.

    In the two clips below, the player enters a set of purple tiles, which has the shader applied to its material.
    Watch for the yellow star effect in the two clips below when the player dies, and you should see it works fine in the second clip, but doesn't render properly in the first.

    Doesn't render inside the shader:


    Renders fine, literally the same scene just a little further to the right:


    Does anyone know what could cause this? Is this a bug in Unity?
    The shader itself is really simple:
    Code (CSharp):
    1. Shader "Vibrant Venture/GravityField"
    2. {
    3.     Properties
    4.     {
    5.         _TintColor ("Tint Color", color) = (1.0,1.0,1.0,1.0)
    6.         _MainTex("Texture", 2D) = "white" {}
    7.         _SineWaveSpeed("Sine Wave Speed", float) = 2.5
    8.         _SineWaveAmplitude("Sine Wave Amplitude", float ) = 0.1
    9.         _SineWaveLength("Sine Wave Length (Inverse)", float) = 0.2
    10.     }
    11.         SubShader
    12.     {
    13.         // Draw after all opaque geometry
    14.         Tags { "Queue"="Transparent" }
    15.  
    16.         // Grab the screen behind the object into _BackgroundTexture
    17.         GrabPass
    18.         {
    19.             "_BackgroundTexture"
    20.         }
    21.  
    22.         // Render the object with the texture generated above, and invert the colors
    23.         Pass
    24.         {
    25.             CGPROGRAM
    26.             #pragma vertex vert
    27.             #pragma fragment frag
    28.             #include "UnityCG.cginc"
    29.  
    30.             struct appdata_t
    31.             {
    32.                 float4 vertex   : POSITION;
    33.                 float4 color    : COLOR;
    34.                 float2 texcoord : TEXCOORD0;
    35.             };
    36.  
    37.             struct v2f
    38.             {
    39.                 float4 vertex : SV_POSITION;
    40.                 float4 grabPos : TEXCOORD0;
    41.                 float3 worldPos : TEXCOORD1;
    42.                 float2 texcoord : TEXCOORD2;
    43.                 fixed4 color    : COLOR;
    44.             };
    45.  
    46.             fixed4 _Color;
    47.             sampler2D _BackgroundTexture;
    48.             sampler2D _MainTex;
    49.             half _SineWaveSpeed;
    50.             half _SineWaveAmplitude;
    51.             half _SineWaveLength;
    52.  
    53.             v2f vert(appdata_t IN) {
    54.                 v2f OUT;
    55.                 OUT.vertex = UnityObjectToClipPos(IN.vertex);
    56.                 OUT.texcoord = IN.texcoord;
    57.                 OUT.grabPos = ComputeGrabScreenPos(OUT.vertex);
    58.                 OUT.color = IN.color * _Color;
    59.                 OUT.worldPos = IN.vertex;
    60.  
    61.                 return OUT;
    62.             }
    63.  
    64.             half4 frag(v2f IN) : SV_Target
    65.             {
    66.                 IN.grabPos.x += sin(_Time.y * _SineWaveSpeed + IN.worldPos.x * _SineWaveLength) * _SineWaveAmplitude * 0.001;
    67.                 IN.grabPos.y += sin(_Time.y * _SineWaveSpeed * 0.5 + IN.worldPos.x * _SineWaveLength) * _SineWaveAmplitude * 0.001;
    68.  
    69.                 float4 tile_color = tex2D(_MainTex, IN.texcoord);
    70.                 const float4 grab_color = tex2Dproj(_BackgroundTexture, IN.grabPos);
    71.  
    72.                 float4 color;
    73.                 color.a = 1.0 - (1.0 - tile_color.a) * (1.0 - grab_color.a);
    74.                 color.r = tile_color.r * tile_color.a / color.a + grab_color.r * grab_color.a * (1.0 - tile_color.a) / color.a;
    75.                 color.g = tile_color.g * tile_color.a / color.a + grab_color.g * grab_color.a * (1.0 - tile_color.a) / color.a;
    76.                 color.b = tile_color.b * tile_color.a / color.a + grab_color.b * grab_color.a * (1.0 - tile_color.a) / color.a;
    77.  
    78.                 return color;
    79.             }
    80.             ENDCG
    81.         }
    82.     }
    83. }
    I noticed that manually setting
    color.a
    to some value "fixes" the problem, although the colors will be off then.