Search Unity

Shader not working after updating Unity

Discussion in 'Shaders' started by Lightrail, Jul 19, 2017.

  1. Lightrail

    Lightrail

    Joined:
    Apr 12, 2013
    Posts:
    37
    I've attached a shader to a screen renderer, however, the parts that should be alpha, are completely black and I can't see what should be on the camera (Culling Mask: Everything).

    The shader worked perfectly before updating Unity to 5.6 (I was on 5.4 before and now I'm on 2017). I have no idea why it's not working and a friend of mine used it and said it was working on his end. Did something update behind the scenes I'm not seeing that changed the way alphas work in Unity?

    Here's the code for my screen renderer:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. [ExecuteInEditMode]
    4. public class ScreenRenderer : MonoBehaviour
    5. {
    6.     public Material mat;
    7.  
    8.     void OnRenderImage(RenderTexture source, RenderTexture destination)
    9.     {
    10.         Graphics.Blit(source, destination, mat);
    11.     }
    12. }
    And here's the shader I'm using:
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "Custom/ScreenRenderer_Circle"
    4. {
    5.     Properties
    6.     {
    7.         _MainTex ("Texture", 2D) = "white" {}
    8.         _Color("Color", Color) = (0,0,0,0)
    9.         _OffX("Offset X", Float) = 0
    10.         _OffY("Offset Y", Float) = 0
    11.         _Radius ("Radius", Range(0, 2.5)) = 0
    12.  
    13.     }
    14.     SubShader
    15.     {
    16.         // No culling or depth
    17.         Cull Off ZWrite Off ZTest Always
    18.  
    19.         Pass
    20.         {
    21.             Tags {
    22.             "Queue" = "Transparent"
    23.             }
    24.  
    25.             Blend SrcAlpha OneMinusSrcAlpha
    26.  
    27.             CGPROGRAM
    28.             #pragma vertex vert
    29.             #pragma fragment frag
    30.            
    31.             #include "UnityCG.cginc"
    32.  
    33.             struct appdata
    34.             {
    35.                 float4 vertex : POSITION;
    36.                 float2 uv : TEXCOORD0;
    37.             };
    38.  
    39.             struct v2f
    40.             {
    41.                 float2 uv : TEXCOORD0;
    42.                 float4 vertex : SV_POSITION;
    43.             };
    44.  
    45.             sampler2D _MainTex;
    46.             float4 _Color;
    47.             float _Radius, _OffX, _OffY;
    48.  
    49.             v2f vert (appdata v)
    50.             {
    51.                 v2f o;
    52.                 o.vertex = UnityObjectToClipPos(v.vertex);
    53.                 o.uv = v.uv;
    54.                 return o;
    55.             }
    56.  
    57.             float4 frag (v2f i) : SV_Target
    58.             {
    59.                 float2 screen = normalize(_ScreenParams.xy);
    60.                 float X = (_OffX - i.uv.x) * screen.x, Y = (_OffY - i.uv.y)  * screen.y;
    61.                 float uvDist = (X * X) + (Y * Y);
    62.                 float cenDist = (_Radius * _Radius) - uvDist;
    63.                 float alphaVal = (cenDist > uvDist) ? 1 : 0;
    64.  
    65.                 return _Color - alphaVal;
    66.             }
    67.             ENDCG
    68.         }
    69.     }
    70. }
    71.  
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    The behavior of OnRenderImage() and Blit() being able to use hardware blending has always struck me as an unintended feature with some performance implications when using MSAA.

    The short version is if you're doing an image effect and using "Blend" in your shader, you're "doing it wrong", or at least using a possibly unintended feature. The _MainTex being passed to the shader is the background that would have been there before, so your shader should instead look like:

    Code (CSharp):
    1. Shader "Custom/ScreenRenderer_Circle"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.         _Color("Color", Color) = (0,0,0,0)
    7.         _OffX("Offset X", Float) = 0
    8.         _OffY("Offset Y", Float) = 0
    9.         _Radius ("Radius", Range(0, 2.5)) = 0
    10.     }
    11.     SubShader
    12.     {
    13.         // No culling or depth
    14.         Cull Off ZWrite Off ZTest Always
    15.         Pass
    16.         {
    17.             CGPROGRAM
    18.             #pragma vertex vert_img
    19.             #pragma fragment frag
    20.        
    21.             #include "UnityCG.cginc"
    22.             sampler2D _MainTex;
    23.             float4 _Color;
    24.             float _Radius, _OffX, _OffY;
    25.             float4 frag (v2f_img i) : SV_Target
    26.             {
    27.                 float2 screen = normalize(_ScreenParams.xy);
    28.                 float X = (_OffX - i.uv.x) * screen.x, Y = (_OffY - i.uv.y)  * screen.y;
    29.                 float uvDist = (X * X) + (Y * Y);
    30.                 float cenDist = (_Radius * _Radius) - uvDist;
    31.                 float alphaVal = (cenDist > uvDist) ? 0 : 1;
    32.                 half4 color = tex2D(_MainTex, i.uv);
    33.                 color.rgb = lerp(color.rgb, _Color.rgb, alphaVal * _Color.a);
    34.                 return color;
    35.             }
    36.             ENDCG
    37.         }
    38.     }
    39. }
    40.  
    The biggest change is sampling the _MainTex and the lerp near the end.

    I'm using vert_img instead of the original vertex function; it's exactly the same code as what was written, and got rid of the Tags since they're not necessary.
     
    Lightrail likes this.
  3. Lightrail

    Lightrail

    Joined:
    Apr 12, 2013
    Posts:
    37
    Thank you very much!

    This fixed everything in that shader and I was able to fix another shader having this same issue.

    I was unaware how much unneeded code was in these shaders. If you have any recommended reading/videos for a beginner to get a better grasp of shader coding, I'd also appreciate it.
     
    klabautermann likes this.
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    Stuff like vert_img and v2f_img are defined in UnityCG.cginc, so just looking through that file will give you a lot of it. Those and the other things I removed don't really hurt anything, they also don't do anything either so it's just visual clutter if you can remove them. If there's anything else you do need to do in the vertex shader it's good to have it there, but for the effect you're doing it's not.

    If you create an Image Effect Shader from the Create > Shader dialog it'll still have the vert function written out, but otherwise it's about as stripped down of an image effect shader as you can get (while still doing something).

    I'd recommend reading this to start with.
    http://www.alanzucconi.com/2015/06/10/a-gentle-introduction-to-shaders-in-unity3d/

    There are a ton of other tutorials out there, both in text and video form. Not all are useful since things have changed over the decade Unity has been out, but it's still a lot of good information.