Search Unity

Non Additive Transparent Shader

Discussion in 'General Graphics' started by mstuehler_fms, Nov 4, 2020.

  1. mstuehler_fms

    mstuehler_fms

    Joined:
    May 7, 2020
    Posts:
    2
    Hi there,

    I would like to use a 'non additive transparent shader' so that I can put a texture on a procedurally generated mesh. That mesh is based on a spline, see the picture below:

    First thing I tried was the build-in transparent/fade shader, but as you can see in the red circles there is an additive overlapping happening.

    Next I tried to use a custom shader with ZWrite off, which lead to result below.

    From my understanding I'd need to use the first Pass to save the transparency of a Fragment to a buffer texture. If another Fragment wants to write to the same Pixel it can only do so if it has a higher alpha value (meaning that a "max" function call would be needed somewhere). Then in a second Pass this should be read from the buffer texture and get applied to the mesh.

    I tried using a GrabPass for this but this did not work out at all.
    However, I've not found anything on how to use a custom buffer texture to transmit the alpha values between Passes, if that's possible.

    Here's what I have so far:

    Code (CSharp):
    1.  
    2. Shader "Custom/NonAdditive"
    3. {
    4.     Properties
    5.     {
    6.         _Color("Main Color", Color) = (1,1,1,1)
    7.         _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
    8.     }
    9.  
    10.         SubShader
    11.     {
    12.         Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
    13.  
    14.         Blend SrcAlpha OneMinusSrcAlpha
    15.         ZWrite off
    16.  
    17.         LOD 200
    18.  
    19.         Pass
    20.         {
    21.             CGPROGRAM
    22.  
    23.             #include "UnityCG.cginc"
    24.  
    25.             #pragma vertex vert
    26.             #pragma fragment frag
    27.  
    28.             sampler2D _MainTex;
    29.             float4 _MainTex_ST;
    30.             fixed4 _Color;
    31.  
    32.             struct appdata
    33.             {
    34.                 float4 vertex : POSITION;
    35.                 float2 uv : TEXCOORD0;
    36.             };
    37.  
    38.             struct v2f
    39.             {
    40.                 float4 position : SV_POSITION;
    41.                 float2 uv : TEXCOORD0;
    42.             };
    43.  
    44.             v2f vert(appdata v)
    45.             {
    46.                 v2f o;
    47.                 o.position = UnityObjectToClipPos(v.vertex);
    48.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    49.                 return o;
    50.             }
    51.  
    52.             fixed4 frag(v2f i) : SV_TARGET
    53.             {
    54.                 fixed4 col = tex2D(_MainTex, i.uv);
    55.                 col.a = _Color.a;
    56.                 //
    57.                 return col;
    58.             }
    59.  
    60.             ENDCG
    61.         }
    62.  
    63.         GrabPass
    64.         {
    65.             "_MainTex2"
    66.         }
    67.  
    68.         Pass
    69.         {
    70.             CGPROGRAM
    71.  
    72.             #include "UnityCG.cginc"
    73.  
    74.             #pragma vertex vert
    75.             #pragma fragment frag
    76.  
    77.             sampler2D _MainTex2;
    78.             float4 _MainTex2_ST;
    79.             fixed4 _Color;
    80.  
    81.             struct appdata
    82.             {
    83.                 float4 vertex : POSITION;
    84.                 float2 uv : TEXCOORD0;
    85.             };
    86.  
    87.             struct v2f
    88.             {
    89.                 float4 position : SV_POSITION;
    90.                 float2 uv : TEXCOORD0;
    91.             };
    92.  
    93.             v2f vert(appdata v)
    94.             {
    95.                 v2f o;
    96.                 o.position = UnityObjectToClipPos(v.vertex);
    97.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex2);
    98.                 return o;
    99.             }
    100.  
    101.             fixed4 frag(v2f i) : SV_TARGET
    102.             {
    103.                 fixed4 col = tex2D(_MainTex2, i.uv);
    104.                 col.xyz *= _Color.xyz;
    105.                 //
    106.                 return col;
    107.             }
    108.  
    109.             ENDCG
    110.         }
    111.     }
    112. }
    So how can I have transparency and non additive overlapping in one shader?

    Any help is appreciated! Maybe you can help me out @bgolus?

    Thanks!
     

    Attached Files:

  2. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,928
    This is not "additive" blending at the edges, it's non-premultiplied alpha blending. You can tell because the edges fade to a blackish color, instead of green.

    You'd need to use premultiplied alpha for correct blending. See: http://es.esotericsoftware.com/forum/Premultiplied-Alpha-Guide-3132

    Setting your blend mode to Blend One OneMinusSrcAlpha and multiplying your rgb values by the alpha in the fragment shader (if your texture is not premultiplied) should get the job done.

    Most of the time, you want to use premultiplied alpha if possible. It not only looks much better, it's sliiiightly faster than regular alpha blending.
     
    Last edited: Nov 5, 2020
  3. mstuehler_fms

    mstuehler_fms

    Joined:
    May 7, 2020
    Posts:
    2
    Hi @arkano22,

    Setting the Blend Mode to 'Blend One OneMinusSrcAlpha' actually worked. Pretty simple solution. See the picture below. I still have to learn a lot, thanks mate :)

    For anyone who want's to use the shader (pretty standard to be honest):

    Code (CSharp):
    1. Shader "Custom/NonAdditive"
    2. {
    3.     Properties
    4.     {
    5.         _Color("Main Color", Color) = (1,1,1,1)
    6.         _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
    7.     }
    8.  
    9.         SubShader
    10.     {
    11.         Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
    12.  
    13.         Blend One OneMinusSrcAlpha
    14.         ZWrite off
    15.  
    16.         LOD 200
    17.  
    18.         Pass
    19.         {
    20.             CGPROGRAM
    21.  
    22.             #include "UnityCG.cginc"
    23.  
    24.             #pragma vertex vert
    25.             #pragma fragment frag
    26.  
    27.             sampler2D _MainTex;
    28.             float4 _MainTex_ST;
    29.             fixed4 _Color;
    30.  
    31.             struct appdata
    32.             {
    33.                 float4 vertex : POSITION;
    34.                 float2 uv : TEXCOORD0;
    35.             };
    36.  
    37.             struct v2f
    38.             {
    39.                 float4 position : SV_POSITION;
    40.                 float2 uv : TEXCOORD0;
    41.             };
    42.  
    43.             v2f vert(appdata v)
    44.             {
    45.                 v2f o;
    46.                 o.position = UnityObjectToClipPos(v.vertex);
    47.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    48.                 return o;
    49.             }
    50.  
    51.             fixed4 frag(v2f i) : SV_TARGET
    52.             {
    53.                 return tex2D(_MainTex, i.uv) * _Color;
    54.             }
    55.  
    56.             ENDCG
    57.         }
    58.     }
    59. }
     

    Attached Files:

    arkano22 likes this.