Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Question Alpha premultiplied on UI Shader

Discussion in 'Shaders' started by luigis, Sep 23, 2023.

  1. luigis

    luigis

    Joined:
    Oct 30, 2013
    Posts:
    25
    Hi!
    I'm using RenderHeads AVPro video system and i'm trying to importing a video clip with alpha.
    The problem is that i have some transparent parts (opacity at 50%) that would be white and are rendered in gray.
    So i've read some threads and i've tried to create a new UI shader and trying to use another blending way

    Code (CSharp):
    1. Blend One OneMinusSrcAlpha
    and then at the bottom
    Code (CSharp):
    1. color.rgb*= color.a
    something is working but not really good
    if I try to
    Code (CSharp):
    1. color.rgb+=color.rgb*color.a;
    2. color.a*=color.a;
    it's near like in after effects (if a use alpha premultiplied)
    I know this formula it's a non sense but i cannot make it work, someone can help me? this is my final shader

    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. Shader "UI/Unlit-Premult"
    4. {
    5.     Properties
    6.     {
    7.          _MainTex ("Base (RGB), Alpha (A)", 2D) = "white" {}
    8.         _Color ("Tint", Color) = (1,1,1,1)
    9.  
    10.         _StencilComp ("Stencil Comparison", Float) = 8
    11.         _Stencil ("Stencil ID", Float) = 0
    12.         _StencilOp ("Stencil Operation", Float) = 0
    13.         _StencilWriteMask ("Stencil Write Mask", Float) = 255
    14.         _StencilReadMask ("Stencil Read Mask", Float) = 255
    15.  
    16.         _ColorMask ("Color Mask", Float) = 15
    17.  
    18.         [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    19.        
    20.     }
    21.  
    22.     SubShader
    23.     {
    24.         Tags
    25.         {
    26.             "Queue"="Transparent"
    27.             "IgnoreProjector"="True"
    28.             "RenderType"="Transparent"
    29.             "PreviewType"="Plane"
    30.             "CanUseSpriteAtlas"="True"
    31.         }
    32.  
    33.         Stencil
    34.         {
    35.             Ref [_Stencil]
    36.             Comp [_StencilComp]
    37.             Pass [_StencilOp]
    38.             ReadMask [_StencilReadMask]
    39.             WriteMask [_StencilWriteMask]
    40.         }
    41.  
    42.         Cull Off
    43.         Lighting Off
    44.         ZWrite Off
    45.         ZTest [unity_GUIZTestMode]
    46.         Blend One OneMinusSrcAlpha    //premult alpha
    47.         ColorMask [_ColorMask]
    48.  
    49.         Pass
    50.         {
    51.             Name "Default"
    52.         CGPROGRAM
    53.             #pragma vertex vert
    54.             #pragma fragment frag
    55.             #pragma target 2.0
    56.  
    57.             #include "UnityCG.cginc"
    58.             #include "UnityUI.cginc"
    59.  
    60.             #pragma multi_compile_local _ UNITY_UI_CLIP_RECT
    61.             #pragma multi_compile_local _ UNITY_UI_ALPHACLIP
    62.  
    63.             struct appdata_t
    64.             {
    65.                 float4 vertex   : POSITION;
    66.                 float4 color    : COLOR;
    67.                 float2 texcoord : TEXCOORD0;
    68.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    69.             };
    70.  
    71.             struct v2f
    72.             {
    73.                 float4 vertex   : SV_POSITION;
    74.                 fixed4 color    : COLOR;
    75.                 float2 texcoord  : TEXCOORD0;
    76.                 float4 worldPosition : TEXCOORD1;
    77.                 UNITY_VERTEX_OUTPUT_STEREO
    78.             };
    79.  
    80.             sampler2D _MainTex;
    81.             fixed4 _Color;
    82.             fixed4 _TextureSampleAdd;
    83.             float4 _ClipRect;
    84.             float4 _MainTex_ST;
    85.  
    86.             v2f vert(appdata_t v)
    87.             {
    88.                 v2f OUT;
    89.                 UNITY_SETUP_INSTANCE_ID(v);
    90.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
    91.                 OUT.worldPosition = v.vertex;
    92.                 OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
    93.  
    94.                 OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
    95.  
    96.                 OUT.color = v.color * _Color;
    97.                 return OUT;
    98.             }
    99.  
    100.             fixed4 frag(v2f IN) : SV_Target
    101.             {
    102.                 half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
    103.  
    104.                 #ifdef UNITY_UI_CLIP_RECT
    105.                 color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
    106.                 #endif
    107.  
    108.                 #ifdef UNITY_UI_ALPHACLIP
    109.                 clip (color.a - 0.001);
    110.                 #endif
    111.                 color.rgb*=color.a;
    112.                 color.a*=color.a;
    113.                
    114.                 //return half4(color.rgb+(color.rgb*color.a),color.a*color.a);
    115.                 return color;
    116.             }
    117.         ENDCG
    118.         }
    119.     }
    120. }
     
  2. luigis

    luigis

    Joined:
    Oct 30, 2013
    Posts:
    25
    I've found this explanation seems fit prefectly but I've tried also to put only Blend One OneMinusSrcAlpha and leave the color as normal and didn't work also...

    Premultiplied Alpha Blending
    There is an important variant of alpha blending: sometimes the fragment output color has its alpha component already premultiplied to the color components. (You might think of it as a price that has VAT already included.) In this case, alpha must not be multiplied again to the colors (corresponding to a rule that VAT must not be added more than once) and the correct blending is:

    Blend One OneMinusSrcAlpha

    which corresponds to:

    float4 result = float4(1.0, 1.0, 1.0, 1.0) * fragment_output + (float4(1.0, 1.0, 1.0, 1.0) - fragment_output.aaaa) * pixel_color;

    Two common mistakes in computer graphics are 1) to use the blend equation for standard alpha blending with premultiplied colors and 2) to use the blend equation for premultiplied alpha blending with colors that are not premultiplied. The visual errors caused by these mistakes can be quite subtle; usually they show up as either darkened or lightened silhouettes of blended objects. Thus, whenever you program a blend equation, make sure that you know whether you are dealing with premultiplied colors or not.
     
    Last edited: Sep 25, 2023
  3. luigis

    luigis

    Joined:
    Oct 30, 2013
    Posts:
    25
    I've solved this by appling the blending option Blend One OneMinusSrcAlpha I don't know why, i was into a testing code labyrith, Started from scratch now works like a charm just adding the correct blend!