0
\$\begingroup\$

I wanted to make build of a project using custom shader for TextMeshPro text assets. It renders nicely on PC but It gives me block instead when build for the meta Quest 2. For me it looks like it doesn't read the alpha from the atlas assets, thus giving block instead of cutout. Is there a way to prevent this behaviour, in build option or shader ?

From unity screen Screenshot from unity scene panel (same result in PCVR build)

Build from meta quest 2 (android) Screenshot from quest 2 build (android)

Here is the shader (URP)

Shader "Unlit/InvertFontAtlas"
{
    Properties 
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        }
    SubShader 
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        Cull off

        Blend SrcAlpha OneMinusSrcAlpha
        AlphaToMask On


        Blend OneMinusDstColor Zero
        AlphaToMask On

        Pass 
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.0 Alpha:Blend

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            
            fixed4 _Color;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
        
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col;
                col.rgb = _Color;
                col.a = tex2D(_MainTex, i.uv).a;
           
                return col;

            }

            ENDCG

        }

    


    }
    FallBack "Diffuse"
}

ANSWER:

As mentionned by Kevin the AlphaToMask On does not render on Android setup. the workaround is to use the clip(alpha - 0.1). It works better with TextMeshPro clip with 0.5 value instead of 0.1 which gives a bolder font. So the corrected shader looks like that:

Shader "Unlit/InvertFontAtlas"
{
    Properties 
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        }
    SubShader 
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        Cull off

        Blend SrcAlpha OneMinusSrcAlpha
        //AlphaToMask On


        Blend OneMinusDstColor Zero
        //AlphaToMask On

        Pass 
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.0 Alpha:Blend

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            
            fixed4 _Color;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
        
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col;
                col.rgb = _Color;
                col.a = tex2D(_MainTex, i.uv).a;
                // here the clip line
                clip(col.a - 0.5);
                return col;

            }

            ENDCG

        }

    


    }
    FallBack "Diffuse"
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Are you certain that the font is available on the device? I've seen the same error on KDE Plasma when the font pack wasn't properly installed. \$\endgroup\$ Jun 1, 2023 at 2:10
  • \$\begingroup\$ Unity create atlas files containing the charset, thus you don't need any installed font assets on your devices. My project has the same font without this shaders and it renders nicely. \$\endgroup\$
    – Felox
    Jun 1, 2023 at 13:40

1 Answer 1

2
\$\begingroup\$

The AlphaToMask flag is intended for use with multisample anti-aliasing MSAA. It's possible that you're using a different quality setting in the Editor than on mobile; if I recall correctly, MSAA is disabled in the default quality setting that is applied to mobile devices.

In general, I would not recommend using MSAA on mobile devices due to the high performance cost.

Additionally, on the Unity forums, bgolus (who is the forums' leading expert on shaders) reports that AlphaToMask is not supported on all Android devices. However, he recommends a simple workaround:

Just adding the below line will fix it.

clip(alpha - 0.1);

Replace alpha with whatever your shader's output alpha is just before the return. That solution will also actually fix the "unsolvable" problem too as it'll ensure alpha testing is being used in the cases that the hardware or drivers aren't properly supporting it.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .