Search Unity

Alpha Value in Fragment Shader

Discussion in 'Shaders' started by Pouleto, Nov 9, 2015.

  1. Pouleto

    Pouleto

    Joined:
    Oct 10, 2015
    Posts:
    3
    Hi!

    I'm currently trying to do something pretty simple : modify the alpha value into a fragment shader. This is the code of my shader :

    Code (CSharp):
    1. Shader "UI/GreenBackgroundRemover" {
    2.     Properties {
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}
    4.     }
    5.    
    6.     SubShader {
    7.  
    8.         Pass {
    9.             CGPROGRAM
    10.             #pragma vertex vert_img
    11.             #pragma fragment frag
    12.  
    13.             #include "UnityCG.cginc"
    14.            
    15.             uniform sampler2D _MainTex;
    16.  
    17.             fixed4 frag(v2f_img i) : SV_Target {
    18.                 fixed4 r = tex2D(_MainTex, i.uv);
    19.                
    20.                 if(r.g >= 0.7f)
    21.                 {
    22.                     r.a = 0;
    23.                     r.g = r.r = r.b = 0;
    24.                 }
    25.                 return r;
    26.             }
    27.             ENDCG
    28.         }
    29.     }
    30. }
    I use this shader into a material.
    Here is my initial texture:
    test.png
    And here is the result of my shader:
    Capture.PNG

    As you can see the pixels are set to black but the alpha value is not modified. Does anyone have an idea about what I'm missing here?

    Thanks in advance for your help!
     
  2. Fuegan

    Fuegan

    Joined:
    Dec 5, 2012
    Posts:
    20
    You are missing a blending method, I don't know how you can add it directly in the fragment shader but you can do it with shaderlab (cf : http://docs.unity3d.com/Manual/SL-Blend.html). In general you just have to add it (
    Blend SrcAlpha OneMinusSrcAlpha) wich is the basic alpha blending.

    Code (CSharp):
    1.     Shader "UI/GreenBackgroundRemover" {
    2.         Properties {
    3.             _MainTex ("Base (RGB)", 2D) = "white" {}
    4.         }
    5.      
    6.         SubShader {
    7.             Blend SrcAlpha OneMinusSrcAlpha
    8.  
    9.             Pass {
    10.                 CGPROGRAM
    11.                 #pragma vertex vert_img
    12.                 #pragma fragment frag
    13.    
    14.                 #include "UnityCG.cginc"
    15.              
    16.                 uniform sampler2D _MainTex;
    17.    
    18.                 fixed4 frag(v2f_img i) : SV_Target {
    19.                     fixed4 r = tex2D(_MainTex, i.uv);
    20.                  
    21.                     if(r.g >= 0.7f)
    22.                     {
    23.                         r.a = 0;
    24.                         r.g = r.r = r.b = 0;
    25.                     }
    26.                     return r;
    27.                 }
    28.                 ENDCG
    29.             }
    30.         }
    31.     }
    32.  
     
  3. Pouleto

    Pouleto

    Joined:
    Oct 10, 2015
    Posts:
    3
    @Fuegan Thanks a lot for your answer! Although it seems there is a rendering order problem, instead of seeing the object behing my plane I see the color of the background of my camera. And what is funny is that it is the good result in the Scene Tab but not in the Game Tab.

    In Scene Tab : Capture.PNG
    In the Game Tab : Capture.PNG

    I'll look further into the link you gave me!
     
  4. Fuegan

    Fuegan

    Joined:
    Dec 5, 2012
    Posts:
    20
    As you don't have any tags set it seems Unity doesn't render your objects in the right order yes.

    Adding this

    Code (CSharp):
    1. Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    between the SubShader and Blend lignes should resolve the problem.

    The main part is "Queue"="Transparent" wich is the order in the queue (Transparent are renderer after opaque objects).

    The RenderType part is for Unity (it will be treated as a transparent object) I don't know exactly what it does but I suppose it has to do with some optimisation.

    IgnoreProjector is usually added to transparent shaders as projectors don't work well with transparency. (But it is useless if you don't use projectors).


    PS : without tags unity sets the objects as "Queue"="Geometry" which means if your background have a standard shader without transparency your plane should have still be rendered last so be sure your objects are not too close (as it can cause flickering).
     
    mertbsn and jhocking like this.
  5. Pouleto

    Pouleto

    Joined:
    Oct 10, 2015
    Posts:
    3
    Thanks for the explanation!
    I finally had to invert the order of my camera and my objects in z to make it work.
     
  6. X28

    X28

    Joined:
    Jul 15, 2015
    Posts:
    8
    Thank you. ;)
     
  7. IliqNikushev

    IliqNikushev

    Joined:
    Feb 1, 2017
    Posts:
    23
    10/10 Blend SrcAlpha OneMinusSrcAlpha solved my issue
    BEFORE
    upload_2021-1-25_16-45-20.png
    AFTER
    upload_2021-1-25_16-44-50.png
     

    Attached Files:

    vvalecha519 likes this.
  8. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    184
    I have a similar problem. I am using a fragment shader and cannot get alpha working.

    Code (CSharp):
    1. Shader "Unlit/SpectrumShader"
    2. {
    3.     Properties {
    4.         _MainTex ("Base (RGB)", 2D) = "white" {}
    5.     }
    6.     SubShader
    7.     {
    8.         Tags {"Queue"="Transparent" "IgnoreProjector"="True"}
    9.         Blend SrcAlpha OneMinusSrcAlpha
    10.  
    11.         Pass
    12.         {
    13.  
    14.  
    15.             CGPROGRAM
    16.             #pragma vertex vert
    17.             #pragma fragment frag
    18.  
    19.             #include "UnityCG.cginc"
    20.  
    21.             struct appdata
    22.             {
    23.                 float4 vertex : POSITION;
    24.                 float2 uv : TEXCOORD0;
    25.             };
    26.  
    27.             struct v2f
    28.             {
    29.                 float2 uv : TEXCOORD0;
    30.                 float4 vertex : SV_POSITION;
    31.                 float4 screenPos : TEXCOORD1;
    32.             };
    33.  
    34.             float _Offset;
    35.             float _MainTex;
    36.  
    37.             v2f vert (appdata v)
    38.             {
    39.                
    40.                 v2f o;
    41.                 UNITY_INITIALIZE_OUTPUT(v2f,o);
    42.                 o.vertex = UnityObjectToClipPos(v.vertex);
    43.                 o.screenPos = ComputeScreenPos(o.vertex);
    44.                 return o;
    45.             }
    46.            
    47.             fixed4 frag (v2f i) : SV_Target
    48.             {
    49.  
    50.                 float colourOffset = i.screenPos.y + _Offset;
    51.                 fixed4 col = float4((colourOffset * 10) % 1.0f, colourOffset % 1.0f, (colourOffset / 10) % 1.0f, 1.0f);
    52.  
    53.                 return col;
    54.             }
    55.             ENDCG
    56.         }
    57.     }
    58.  
    59. }
    60.  
    Can anyone provide me with some guidance to get alpha working? I have my shader on a material, I apply the material to a sprite (say, a donut) and there is no alpha (the donut will look like a solid circle).
     
  9. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    184
    Anyone have an idea of how I can get alpha working with a fragment shader?
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Set it to something other than 1.0?

    That float4 you’re setting, the 4 components are red, green, blue, and alpha. And you’re setting the alpha to 1.0.
     
  11. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    184
    Thank you, yes. I do understand if I set that to 0.5 it will be half opacity for the entire material. However, the issue that I am having is I would like to 'knock out' the pieces that are transparent and show the pieces that are opaque. Does that make sense? Sorry, I am a complete shader noob and have been trying to figure out what I should be doing here. I really appreciate any help you can provide.

    I have attached a screenshot of what I mean. For example the sprite on the left is a donut. And the sprite on the right should be too (it is the same sprite) however it is showing as a solid circle with my shader. How can I make my shader also have the hole in the middle?
     

    Attached Files:

    Last edited: Feb 28, 2021
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    There's absolutely nothing in your shader making it a circle. I suspect your "donut" sprite is set to use a tight sprite mesh, which is generating a circular mesh, and that's what you're seeing when you use your shader.

    If you want your shader to have the same alpha as your sprite, then you need to sample the sprite texture in your shader and use just the alpha. See the default sprite shader, and the cginc file that most of the actual useful shader code is in.
    https://github.com/TwoTailsGames/Un.../DefaultResourcesExtra/Sprites-Default.shader
    https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/CGIncludes/UnitySprites.cginc
    Copy the parts from the
    SpriteVert
    and
    SpriteFrag
    functions you need.

    And maybe go through some beginner tutorials on shaders if you're still having issues.
    https://www.alanzucconi.com/2015/06/10/a-gentle-introduction-to-shaders-in-unity3d/
    (there are 5 parts)