Unity3D:模糊 UI 画布的背景

Posted

技术标签:

【中文标题】Unity3D:模糊 UI 画布的背景【英文标题】:Unity3D : Blur the background of a UI canvas 【发布时间】:2015-03-13 10:49:19 【问题描述】:

我正在尝试在 Unity3D 中为我的游戏的 UI 窗口的背景创建模糊效果。

我现在能想到的最好的例子之一是风暴英雄,注意升级面板的背景如何模糊它背后的东西:

有什么方法可以在 Unity3D 中使用最近添加的 Canvas 重现相同的效果? 我知道有一种方法可以通过使用相机来做到这一点,但我对整个事情并不是很熟悉,尤其是在使用新的 UI 系统时。

谢谢。

【问题讨论】:

模糊背景可能会占用大量 CPU。您有时可以通过将背景的静态模糊版本放在顶部来做一个技巧 事实上,我认为这就是您的示例中所做的。你可以看到数字 2 没有模糊 @Ewan 请参阅 this 和 this。这不是静态模糊。此外,与游戏中的屏幕截图不同,在菜单中位于对话后面时,动画也会变得模糊。 在这种情况下,第二个摄像头带有模糊着色器 【参考方案1】:

这是一个非常适合我的着色器脚本。

来源:https://forum.unity3d.com/threads/solved-dynamic-blurred-background-on-ui.345083/#post-2853442

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unlit/FrostedGlass"

    Properties
    
        _Radius("Radius", Range(1, 255)) = 1
    

    Category
    
        Tags "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Opaque" 

        SubShader
        
            GrabPass
            
                Tags "LightMode" = "Always" 
            

            Pass
            
                Tags "LightMode" = "Always" 

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t
                
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                ;

                struct v2f
                
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                ;

                v2f vert(appdata_t v)
                
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    return o;
                

                sampler2D _GrabTexture;
                float4 _GrabTexture_TexelSize;
                float _Radius;

                half4 frag(v2f i) : COLOR
                
                    half4 sum = half4(0,0,0,0);

                    #define GRABXYPIXEL(kernelx, kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely, i.uvgrab.z, i.uvgrab.w)))

                    sum += GRABXYPIXEL(0.0, 0.0);
                    int measurments = 1;

                    for (float range = 0.1f; range <= _Radius; range += 0.1f)
                    
                        sum += GRABXYPIXEL(range, range);
                        sum += GRABXYPIXEL(range, -range);
                        sum += GRABXYPIXEL(-range, range);
                        sum += GRABXYPIXEL(-range, -range);
                        measurments += 4;
                    

                    return sum / measurments;
                
                ENDCG
            
            GrabPass
            
                Tags "LightMode" = "Always" 
            

            Pass
            
                Tags "LightMode" = "Always" 

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t
                
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                ;

                struct v2f
                
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                ;

                v2f vert(appdata_t v)
                
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    return o;
                

                sampler2D _GrabTexture;
                float4 _GrabTexture_TexelSize;
                float _Radius;

                half4 frag(v2f i) : COLOR
                

                    half4 sum = half4(0,0,0,0);
                    float radius = 1.41421356237 * _Radius;

                    #define GRABXYPIXEL(kernelx, kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely, i.uvgrab.z, i.uvgrab.w)))

                    sum += GRABXYPIXEL(0.0, 0.0);
                    int measurments = 1;

                    for (float range = 1.41421356237f; range <= radius * 1.41; range += 1.41421356237f)
                    
                        sum += GRABXYPIXEL(range, 0);
                        sum += GRABXYPIXEL(-range, 0);
                        sum += GRABXYPIXEL(0, range);
                        sum += GRABXYPIXEL(0, -range);
                        measurments += 4;
                    

                    return sum / measurments;
                
                ENDCG
            
        
    

【讨论】:

有什么简单的理由可以解释为什么这个着色器会自行环回?即背景模糊逐帧反馈给自身,导致每一帧都更加模糊(这本身是一种简洁的效果,但并不是我真正想要的) 尝试在iPhone 8+上使用,全屏图像模糊,值15。它很快让手机发热。下面的shader就没有这个问题了。 据我了解,此着色器 (A) 和下方 (B) 之间的差异非常显着。 A 具有 O(r^2) 复杂度并且更接近真实模糊(大 r 会导致性能问题)。 B 的复杂度为 O(r),而且更简单。我们根据我们的要求调整了 B 着色器,它很轻并且工作正常。请记住,您的要求可能会有所不同。【参考方案2】:

我稍微修改了这个。添加了tint colorUI兼容性。虽然在 UI 上使用时是可能的,但会使之前的 UI 不可见。

    // Based on cician's shader from https://forum.unity3d.com/threads/simple-optimized-blur-shader.185327/#post-1267642

Shader "Custom/MaskedUIBlur" 
    Properties 
        _Size ("Blur", Range(0, 30)) = 1
        [HideInInspector] _MainTex ("Masking Texture", 2D) = "white" 
        _AdditiveColor ("Additive Tint color", Color) = (0, 0, 0, 0)
        _MultiplyColor ("Multiply Tint color", Color) = (1, 1, 1, 1)
    

    Category 

        // We must be transparent, so other objects are drawn before this one.
        Tags  "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Opaque" 


        SubShader
        
            // Horizontal blur
            GrabPass
            
                "_HBlur"
            
            /*
            ZTest Off
            Blend SrcAlpha OneMinusSrcAlpha
            */

            Cull Off
            Lighting Off
            ZWrite Off
            ZTest [unity_GUIZTestMode]
            Blend SrcAlpha OneMinusSrcAlpha

            Pass
                      
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t 
                    float4 vertex : POSITION;
                    float2 texcoord : TEXCOORD0;
                ;

                struct v2f 
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                    float2 uvmain : TEXCOORD1;
                ;

                sampler2D _MainTex;
                float4 _MainTex_ST;

                v2f vert (appdata_t v)
                
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);

                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif

                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y * scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;

                    o.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);
                    return o;
                

                sampler2D _HBlur;
                float4 _HBlur_TexelSize;
                float _Size;
                float4 _AdditiveColor;
                float4 _MultiplyColor;

                half4 frag( v2f i ) : COLOR
                   
                    half4 sum = half4(0,0,0,0);

                    #define GRABPIXEL(weight,kernelx) tex2Dproj( _HBlur, UNITY_PROJ_COORD(float4(i.uvgrab.x + _HBlur_TexelSize.x * kernelx * _Size, i.uvgrab.y, i.uvgrab.z, i.uvgrab.w))) * weight

                    sum += GRABPIXEL(0.05, -4.0);
                    sum += GRABPIXEL(0.09, -3.0);
                    sum += GRABPIXEL(0.12, -2.0);
                    sum += GRABPIXEL(0.15, -1.0);
                    sum += GRABPIXEL(0.18,  0.0);
                    sum += GRABPIXEL(0.15, +1.0);
                    sum += GRABPIXEL(0.12, +2.0);
                    sum += GRABPIXEL(0.09, +3.0);
                    sum += GRABPIXEL(0.05, +4.0);


                    half4 result = half4(sum.r * _MultiplyColor.r + _AdditiveColor.r, 
                                        sum.g * _MultiplyColor.g + _AdditiveColor.g, 
                                        sum.b * _MultiplyColor.b + _AdditiveColor.b, 
                                        tex2D(_MainTex, i.uvmain).a);
                    return result;
                
                ENDCG
            

            // Vertical blur
            GrabPass
            
                "_VBlur"
            

            Pass
                      
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t 
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                ;

                struct v2f 
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                    float2 uvmain : TEXCOORD1;
                ;

                sampler2D _MainTex;
                float4 _MainTex_ST;

                v2f vert (appdata_t v) 
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);

                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif

                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y * scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;

                    o.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);

                    return o;
                

                sampler2D _VBlur;
                float4 _VBlur_TexelSize;
                float _Size;
                float4 _AdditiveColor;
                float4 _MultiplyColor;

                half4 frag( v2f i ) : COLOR
                
                    half4 sum = half4(0,0,0,0);

                    #define GRABPIXEL(weight,kernely) tex2Dproj( _VBlur, UNITY_PROJ_COORD(float4(i.uvgrab.x, i.uvgrab.y + _VBlur_TexelSize.y * kernely * _Size, i.uvgrab.z, i.uvgrab.w))) * weight

                    sum += GRABPIXEL(0.05, -4.0);
                    sum += GRABPIXEL(0.09, -3.0);
                    sum += GRABPIXEL(0.12, -2.0);
                    sum += GRABPIXEL(0.15, -1.0);
                    sum += GRABPIXEL(0.18,  0.0);
                    sum += GRABPIXEL(0.15, +1.0);
                    sum += GRABPIXEL(0.12, +2.0);
                    sum += GRABPIXEL(0.09, +3.0);
                    sum += GRABPIXEL(0.05, +4.0);

                    half4 result = half4(sum.r * _MultiplyColor.r + _AdditiveColor.r, 
                                        sum.g * _MultiplyColor.g + _AdditiveColor.g, 
                                        sum.b * _MultiplyColor.b + _AdditiveColor.b, 
                                        tex2D(_MainTex, i.uvmain).a);
                    return result;
                
                ENDCG
            
        
    

【讨论】:

这对我很有用(但是,选择的答案版本没有)。谢谢! 效果很好,谢谢!我需要将模糊的背景设为灰度而不是彩色,因此我修改了着色器,为 gist.github.com/jhocking/9de4197daf84698a60e51c67695d2be3 添加了一个切换开关 我们如何将它与 URP 一起使用? 在统一 2020.3 中会导致“材料没有 _Stencil 属性”

以上是关于Unity3D:模糊 UI 画布的背景的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D中UI图片模糊,不清晰解决怎么解决

Unity3D中UI图片模糊,不清晰解决如何解决

Unity3d游戏开发浅谈UGUI中的Canvas以及三种画布渲染模式

Unity3D 官方移动游戏优化指南9.用户界面

嵌套画布优化 unity3d 2019.3

Unity3D中UI图片模糊,不清晰解决怎么解决