Android rendering glitches with UnityPlayer in front of WebView

Hi,
my project setup on Android includes WebView which is injected behind the UnityPlayer.

The unityPlayer is subclassed to set a translucent pixel format for the player SurfaceView.

public class CustomUnityPlayer extends UnityPlayer
{
    ...
    public void addView(View child) {
        if (child instanceof SurfaceView) {
            final SurfaceView surfaceView = (SurfaceView) child;
            surfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
            surfaceView.setZOrderOnTop(true);
        }
        super.addView(child);
    }
}

The plugin later also injects the WebView into the layout.

This works all fine except that any transparent UI canvas element that is rendered on top of an opaque ui element somehow leaves the frame buffer to being transparent in that area with the result that it is blended against the WebView behind.

You can see in the screenshot that the progress bar is showing some elements from the webview behind. The progress bar however is not supposed to be transparent. It’s an opaque image with some transparent shine effect rendered on top. But this transparent image sets the alpha value for the final frame buffer.

164260-screenshot-2020-07-28-at-163721.png

Any ideas how this can be prevented?

Ok the solution I picked to this is to create a copy of the default UI shader and instead of having the

Blend SrcAlpha OneMinusSrcAlpha

blend mode, use

Blend One OneMinusSrcAlpha

and in the fragment shader, manually apply the alpha to the colors rgb values like so:

            fixed4 frag(v2f IN) : SV_Target
            {
                half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
                
                #ifdef UNITY_UI_CLIP_RECT
                color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                #endif

                #ifdef UNITY_UI_ALPHACLIP
                clip (color.a - 0.001);
                #endif

                // pre-multiply the alpha into the color
                color.rgb *= color.a;

                return color;
            }

Everything except the commented line is the default implementation of the UI shader.

I then created a material “TransparentUIElement” which uses that shader and assign it to every ui element that has transparency of some sort.

This includes images, text with an outline, et