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

Blur Background

Discussion in 'UI Toolkit' started by Stroustrup, May 22, 2020.

  1. Stroustrup

    Stroustrup

    Joined:
    May 18, 2020
    Posts:
    142
    How would you go about blurring the background in ui builder?
     
  2. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    970
    Filters aren't yet supported out-of-the-box with UI Toolkit. That's something that's on the roadmap.

    In the short term, if you feel adventurous, you can grab the background, blur it with a simple blur shader, and use it (or a portion of it) as the background of your root VisualElement.

    Getting your hand on the background depends on the render pipeline that you use:
    - On legacy, you can use a "grab pass": https://docs.unity3d.com/Manual/SL-GrabPass.html
    - With URP, look for _CameraOpaqueTexture: https://docs.unity3d.com/Packages/c...s.universal@7.1/manual/universalrp-asset.html

    Hope this helps.
     
  3. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Has anyone gotten this to work? Getting the background into a RenderTexture isn't hard, but its position will not be aligned with the UI element (it will be the whole screen).

    upload_2021-7-29_18-35-42.png
     
  4. AlexandreT-unity

    AlexandreT-unity

    Unity Technologies

    Joined:
    Feb 1, 2018
    Posts:
    324
    Display the texture with an Image instead, and set the sourceRect value according to the position/size of your element.
     
    burningmime likes this.
  5. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Thanks!!!
     
  6. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    @AlexandreT-unity Sorry to ask, but I can't seem to figure out how to get the (post-transformation) position and size in screen space. My attempt was this:

    Code (CSharp):
    1. Rect worldBound = _container.worldBound;
    2. Vector3 worldMin = new Vector3(worldBound.xMin, worldBound.yMin, 0);
    3. Vector3 worldMax = new Vector3(worldBound.xMax, worldBound.yMax, 0);
    4. Vector2 screenMin = _mainCamera.WorldToScreenPoint(worldMin);
    5. Vector2 screenMax = _mainCamera.WorldToScreenPoint(worldMax);
    6. Rect screenRect = Utils.absRect(screenMin, screenMax);
    7. if(_container.sourceRect != screenRect)
    8.     _container.sourceRect = screenRect;
    But that seems like it's about the same as before, if not worse.

    upload_2021-7-29_22-50-48.png
     
  7. AlexandreT-unity

    AlexandreT-unity

    Unity Technologies

    Joined:
    Feb 1, 2018
    Posts:
    324
    Sorry for the confusion but VisualElement.worldBound doesn't necessarily match the world observed by the Camera. It should have been named panelBound because it's the value in panel space. Depending on the UI scaling/dpi and camera transformation, the panel space, world space, and screen space, may not match.

    So basically what you need to do is to bring the screen rect into panel space. For that, convert the screen-space bottom/left and top/right corners of the screen with
    RuntimePanelUtils.ScreenToPanel
    . Then get the image element world rect (panel space rect). And finally convert these into absolute texture coordinates.

    So it should somewhat look like this:
    Code (CSharp):
    1. // Coordinates of the screen in panel space
    2. var screenBLPanel = RuntimePanelUtils.ScreenToPanel(panel, new Vector2(0, 0));
    3. var screenTRPanel = RuntimePanelUtils.ScreenToPanel(panel, new Vector(Screen.width, Screen.height));
    4. var screenWPanel = screenTRPanel.x - screenBLPanel.x;
    5. var screenHPanel = screenTRPanel.y - screenBLPanel.y;
    6.  
    7. // Coordinates of the VisualElement in panel space
    8. var vePanel = image.worldBound
    9.  
    10. // Convert to texture coordinates
    11. // Remember: panel space y axis increases downwards!
    12. float left = Mathf.Abs((vePanel.xMin - screenBLPanel.x) / screenWPanel * textureWidth);
    13. float right = Mathf.Abs((vePanel.xMax - screenBLPanel.x) / screenWPanel * textureWidth);
    14. float bottom = Mathf.Abs((vePanel.yMax - screenTRPanel.y) / screenHPanel * textureHeight);
    15. float top = Mathf.Abs((vePanel.yMin - screenTRPanel.y) / screenHPanel * textureHeight);
    16.  
    17. image.sourceRect = new Rect(left, bottom, right - left, top - bottom);
     
    Last edited: Jul 30, 2021
    Nexer8 and burningmime like this.
  8. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    It's still not working, but could it be because it is a RenderTexture?

    I logged out all the results and see this:

    Code (CSharp):
    1. screenBLPanel=(0.00, 0.00)
    2. screenTRPanel=(1561.00, 817.00)
    3. vePanel=(x:100.00, y:100.00, width:1361.00, height:617.00)
    4. left=100
    5. right=1461
    6. top=717
    7. bottom=100
    8. sourceRect=(x:100.00, y:100.00, width:1361.00, height:617.00)
    9. uv=(x:0.06, y:0.12, width:0.87, height:0.76)
    10.  
    Which all looks good; it's even setting the UV rect to what I would assume is correct. But then...

    upload_2021-7-30_19-23-10.png

    The yellow rect is the border of the image control (I added it to help visualize). So the image is somehow being scaled down and there's a 100 pixel border on the INSIDE of the image rect (but only in the X axis) causing the display to be off. And it's still using the whole screen (notice the door on the right) instead of the specified UV rect.
     
    Last edited: Jul 31, 2021
  9. AlexandreT-unity

    AlexandreT-unity

    Unity Technologies

    Joined:
    Feb 1, 2018
    Posts:
    324
    You need to set image.scaleMode to StretchToFill. I also noticed that the documentation of sourceRect mentions "The source rectangle inside the texture relative to the top left corner". I wrote that code assuming that it was relative to the bottom left corner, so you might have to adjust the code for that (it may not be observable as long as you are vertically centered).
     
    burningmime likes this.
  10. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Woah thanks for answering (on a Saturday morning no less; go get some weekend!) So it is wotrking, although the edges are not rounded, but I assume that's just a limitation of the image control and I should hide it a different way:

    upload_2021-7-30_23-1-41.png
     
  11. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Hey if anyone in the future is searching for this, here's how I'm doing the background image:

    Code (CSharp):
    1. using System;
    2. using burningmime.unity.graphics;
    3. using UnityEngine;
    4. using UnityEngine.UIElements;
    5. using UDebug = UnityEngine.Debug;
    6.  
    7. namespace burningmime.unity.ui
    8. {
    9.     public class GlassyPanel : IDisposable
    10.     {
    11.         private readonly Image _image;
    12.         private readonly IMenuBackground _background;
    13.         private Vector2 _oldScreenSize;
    14.         private Rect _oldPanelRect;
    15.        
    16.         public GlassyPanel(Image image)
    17.         {
    18.             _image = image;
    19.             _image.scaleMode = ScaleMode.StretchToFill;
    20.             _background = Inject.get<IMenuBackgroundService>().getBackground();
    21.         }
    22.        
    23.         public void update()
    24.         {
    25.             RenderTexture texture = _background.texture;
    26.             bool imageChanged = _image.image != _background.texture;
    27.             if(imageChanged)
    28.                 _image.image = texture;
    29.                
    30.            
    31.             if(texture != null)
    32.             {
    33.                 Vector2 screenSize = new(Screen.width, Screen.height);
    34.                 Rect panelRect = _image.worldBound;
    35.                 bool refreshUVs = imageChanged || screenSize != _oldScreenSize || panelRect != _oldPanelRect;
    36.                 if(refreshUVs)
    37.                 {
    38.                     _oldScreenSize = screenSize;
    39.                     _oldPanelRect = panelRect;
    40.                    
    41.                     // Coordinates of the screen in panel space
    42.                     IPanel panel = _image.panel;
    43.                     var screenBLPanel = RuntimePanelUtils.ScreenToPanel(panel, new Vector2(0, 0));
    44.                     var screenTRPanel = RuntimePanelUtils.ScreenToPanel(panel, screenSize);
    45.                     var screenWPanel = Math.Abs(screenTRPanel.x - screenBLPanel.x);
    46.                     var screenHPanel = Math.Abs(screenTRPanel.y - screenBLPanel.y);
    47.  
    48.                     // Convert to texture coordinates
    49.                     // Remember: panel space y axis increases downwards!
    50.                     float left = Mathf.Abs((panelRect.xMin - screenBLPanel.x) / screenWPanel * texture.width);
    51.                     float right = Mathf.Abs((panelRect.xMax - screenBLPanel.x) / screenWPanel * texture.width);
    52.                     float bottom = Mathf.Abs((panelRect.yMax - screenTRPanel.y) / screenHPanel * texture.height);
    53.                     float top = Mathf.Abs((panelRect.yMin - screenTRPanel.y) / screenHPanel * texture.height);
    54.                     _image.sourceRect = Utils.absRect(new Vector2(left, top), new Vector2(right, bottom));
    55.                     _image.MarkDirtyRepaint();
    56.                 }
    57.             }
    58.         }
    59.  
    60.         public void Dispose()
    61.         {
    62.             _image.image = null;
    63.             _background.Dispose();
    64.         }
    65.     }
    66. }
    And the background blur (using SRP):

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Rendering;
    4. using UnityEngine.Rendering.Universal;
    5. using UDebug = UnityEngine.Debug;
    6.  
    7. namespace burningmime.unity.graphics
    8. {
    9.     [Singleton(SingletonScope.PROJECT)]
    10.     class MenuBackgroundService : MonoBehaviour, IMenuBackgroundService
    11.     {
    12.         private const float RESIZE_DELAY = .2f;
    13.         private RenderPassService _passService;
    14.         private MenuBackgroundRenderPass _pass;
    15.         private Material _material;
    16.         private float _totalTime;
    17.         private RenderTexture _target;
    18.         private int _refCount;
    19.         private Vector2Int _resizeTo;
    20.         private Vector2Int _currentSize;
    21.         private float _resizeTimer;
    22.  
    23.         private void Start()
    24.         {
    25.             enabled = false;
    26.             _passService = Inject.get<RenderPassService>();
    27.             _material = new Material(Inject.get<GraphicsResources>().UIBackgroundBlur);
    28.             _material.SetFloat(Shader.PropertyToID("_blurriness"), 1);
    29.             _pass = new MenuBackgroundRenderPass(this);
    30.         }
    31.  
    32.         private void incremenetRefCount()
    33.         {
    34.             if(_refCount <= 0)
    35.             {
    36.                 _refCount = 1;
    37.                 _passService.addPass(_pass);
    38.                 _target = new RenderTexture(Screen.width, Screen.height, 0);
    39.                 _currentSize = new Vector2Int(Screen.width, Screen.height);
    40.                 enabled = true;
    41.             }
    42.             else
    43.             {
    44.                 ++_refCount;
    45.             }
    46.         }
    47.  
    48.         private void decrementRefCount()
    49.         {
    50.             if(_refCount > 1)
    51.                 --_refCount;
    52.             else
    53.                 doDestroy();
    54.         }
    55.  
    56.         private void Update()
    57.         {
    58.             if(_refCount <= 0)
    59.             {
    60.                 doDestroy();
    61.                 return;
    62.             }
    63.  
    64.             Vector2Int newSize = new(Screen.width, Screen.height);
    65.             if(newSize != _currentSize)
    66.             {
    67.                 if(newSize == _resizeTo)
    68.                 {
    69.                     _resizeTimer += Time.unscaledDeltaTime;
    70.                     if(_resizeTimer > RESIZE_DELAY)
    71.                     {
    72.                         _target.safeDestroy();
    73.                         _target = new RenderTexture(newSize.x, newSize.y, 0);
    74.                         _resizeTo = newSize;
    75.                         _currentSize = newSize;
    76.                         _resizeTimer = 0;
    77.                     }
    78.                 }
    79.                 else
    80.                 {
    81.                     _resizeTo = newSize;
    82.                     _resizeTimer = 0;
    83.                 }
    84.             }
    85.         }
    86.  
    87.         private void OnDestroy() => doDestroy();
    88.         private void doDestroy()
    89.         {
    90.             _refCount = 0;
    91.             _passService.removePass(_pass);
    92.             _target.safeDestroy();
    93.             _target = null;
    94.             enabled = false;
    95.         }
    96.  
    97.         public IMenuBackground getBackground() => new MenuBackground(this);
    98.         private class MenuBackground : IMenuBackground // not pooling it because it's not used oftene nough to warrant it and UI has a ton of allocations anyway
    99.         {
    100.             private readonly MenuBackgroundService _owner;
    101.             private bool _isDisposed;
    102.             public MenuBackground(MenuBackgroundService owner) { _owner = owner; owner.incremenetRefCount(); }
    103.             public RenderTexture texture => _owner._target;
    104.             public void Dispose() { if(!_isDisposed) _owner.decrementRefCount(); _isDisposed = true; }
    105.         }
    106.  
    107.         private class MenuBackgroundRenderPass : SRPUtil.BaseRenderPass
    108.         {
    109.             private readonly MenuBackgroundService _owner;
    110.             private RenderTargetHandle _rtIntermediate;
    111.  
    112.             public MenuBackgroundRenderPass(MenuBackgroundService owner) : base(RenderPassEvent.AfterRendering)
    113.             {
    114.                 _owner = owner;
    115.                 _rtIntermediate.Init("_" + nameof(MenuBackgroundRenderPass) + "_Intermediate");
    116.             }
    117.  
    118.             protected override void executeImpl(ScriptableRenderContext ctx, CommandBuffer cmd, ref RenderingData rd)
    119.             {
    120.                 if(_owner._target != null)
    121.                 {
    122.                     RenderTextureDescriptor intermediateDesc = describeIntermediateTarget(rd.cameraData.cameraTargetDescriptor);
    123.                     cmd.GetTemporaryRT(_rtIntermediate.id, intermediateDesc, FilterMode.Bilinear);
    124.                     Blit(cmd, rd.cameraData.renderer.cameraColorTarget, _rtIntermediate.Identifier(), _owner._material, 0);
    125.                     Blit(cmd, _rtIntermediate.Identifier(), _owner._target, _owner._material, 1);
    126.                     cmd.ReleaseTemporaryRT(_rtIntermediate.id);
    127.                 }
    128.             }
    129.          
    130.             private static RenderTextureDescriptor describeIntermediateTarget(in RenderTextureDescriptor cameraRT)
    131.             {
    132.                 RenderTextureDescriptor rt = cameraRT;
    133.                 rt.depthBufferBits = 0;
    134.                 rt.msaaSamples = 1;
    135.                 return rt;
    136.             }
    137.         }
    138.     }
    139. }
    And the blur shader:

    Code (CSharp):
    1. // Offset and weight numbers taken from: https://forum.unity3d.com/threads/simple-optimized-blur-shader.185327/#post-1267642
    2. Shader "burningmime/UIBackgroundBlur"
    3. {
    4.     Properties
    5.     {
    6.         _blurriness ("Blurriness", Range(0, 30)) = 1
    7.         [HideInInspector] _MainTex ("MainTex", 2D) = "white" {}
    8.     }
    9.  
    10.     HLSLINCLUDE
    11.         #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    12.         struct a2v { float4 position : POSITION; float2 uv: TEXCOORD0; };
    13.         struct v2f { float4 position : SV_POSITION; float2 uv : TEXCOORD0; };
    14.  
    15.         sampler2D _MainTex;
    16.         float4 _MainTex_ST;
    17.         float4 _MainTex_TexelSize;
    18.         float _blurriness;
    19.      
    20.         static const float BLUR_DISTANCE_MULT = 4;
    21.  
    22.         v2f fullscreen_VS(a2v IN)
    23.         {
    24.             v2f OUT;
    25.             OUT.position = TransformObjectToHClip(IN.position.xyz);
    26.             OUT.uv = IN.uv;
    27.             return OUT;
    28.         }
    29.  
    30.         #define BLUR_SAMPLE_COORD(COORD, OFS) saturate(IN.uv.COORD + OFS * BLUR_DISTANCE_MULT * _MainTex_TexelSize.COORD * _blurriness)
    31.         #define BLUR_SAMPLE_COORDS_X(OFS) float2(BLUR_SAMPLE_COORD(x, OFS), IN.uv.y)
    32.         #define BLUR_SAMPLE_COORDS_Y(OFS) float2(IN.uv.x, BLUR_SAMPLE_COORD(y, OFS))
    33.         #define BLUR_SAMPLE_ADD(IS_X, WEIGHT, OFS) sum += tex2D(_MainTex, (IS_X ? BLUR_SAMPLE_COORDS_X(OFS) : BLUR_SAMPLE_COORDS_Y(OFS))) * WEIGHT;
    34.         #define BLUR_SAMPLE_FUNC(IS_X) \
    35.             float4 sum = float4(0, 0, 0, 0); \
    36.             BLUR_SAMPLE_ADD(IS_X, 0.05, -4.0) \
    37.             BLUR_SAMPLE_ADD(IS_X, 0.09, -3.0) \
    38.             BLUR_SAMPLE_ADD(IS_X, 0.12, -2.0) \
    39.             BLUR_SAMPLE_ADD(IS_X, 0.15, -1.0) \
    40.             BLUR_SAMPLE_ADD(IS_X, 0.18,  0.0) \
    41.             BLUR_SAMPLE_ADD(IS_X, 0.15, +1.0) \
    42.             BLUR_SAMPLE_ADD(IS_X, 0.12, +2.0) \
    43.             BLUR_SAMPLE_ADD(IS_X, 0.09, +3.0) \
    44.             BLUR_SAMPLE_ADD(IS_X, 0.05, +4.0)
    45.  
    46.         float4 blurHoriz_PS(v2f IN) : SV_Target
    47.         {
    48.             BLUR_SAMPLE_FUNC(true)
    49.             return float4(sum.xyz, 1);
    50.         }
    51.  
    52.         float4 blurVert_PS(v2f IN) : SV_Target
    53.         {
    54.             BLUR_SAMPLE_FUNC(false)
    55.             //float3 hsv = rgb2hsv(sum.xyz);
    56.             //hsv.y = saturate(hsv.y - DESATURATE_SUB * _blurriness) * lerp(1, DESATURATE_MULT, _blurriness);
    57.             //return float4(hsv2rgb(hsv), 1);
    58.             return float4(sum.xyz, 1);
    59.         }
    60.     ENDHLSL
    61.  
    62.     SubShader
    63.     {
    64.         Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
    65.      
    66.         Pass
    67.         {
    68.             Tags { "LightMode" = "SRPDefaultUnlit" }
    69.             ZTest Always
    70.             ZWrite Off
    71.             Cull Off
    72.             HLSLPROGRAM
    73.                 #pragma vertex fullscreen_VS
    74.                 #pragma fragment blurHoriz_PS
    75.             ENDHLSL
    76.         }
    77.      
    78.         Pass
    79.         {        
    80.             Tags { "LightMode" = "SRPDefaultUnlit" }
    81.             ZTest Always
    82.             ZWrite Off
    83.             Cull Off
    84.             HLSLPROGRAM
    85.                 #pragma vertex fullscreen_VS
    86.                 #pragma fragment blurVert_PS
    87.             ENDHLSL
    88.         }
    89.     }
    90. }
    It has a few references to internal utility classes, but it should give the general idea.
     
    Last edited: Jul 31, 2021
  12. AlexandreT-unity

    AlexandreT-unity

    Unity Technologies

    Joined:
    Feb 1, 2018
    Posts:
    324
    You're welcome, glad you got it to work :)

    With the Image element, the image is drawn as a foreground, like text. If you want rounded corners that will clip the image, set overflow to hidden and set border-bottom/top-left/right-radius > 0.
     
    burningmime likes this.
  13. Oneiros90

    Oneiros90

    Joined:
    Apr 29, 2014
    Posts:
    77
    I tried to create a custom VisualElement with Uxml attributes for blur parameters (so it would be controllable from uxml and builder) but I'm not getting any meaningful result.
    Would anybody be able to tell me what's wrong with my code?

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UIElements;
    3.  
    4. namespace Test
    5. {
    6.     public class BlurImage : VisualElement
    7.     {
    8.         private readonly Material _blurMaterial = new(Shader.Find("Custom/Blur"));
    9.  
    10.         private Texture _srcTexture;
    11.         private RenderTexture _destTexture;
    12.  
    13.         public int Radius
    14.         {
    15.             get => _blurMaterial.GetInt("_Radius");
    16.             set
    17.             {
    18.                 _blurMaterial.SetInt("_Radius", value);
    19.                 BlurTexture();
    20.             }
    21.         }
    22.  
    23.         public BlurImage()
    24.         {
    25.  
    26.             RegisterCallback<GeometryChangedEvent>(evt =>
    27.             {
    28.                 BlurTexture();
    29.             });
    30.  
    31.             RegisterCallback<AttachToPanelEvent>(evt =>
    32.             {
    33.                 BlurTexture();
    34.             });
    35.         }
    36.  
    37.         private void BlurTexture()
    38.         {
    39.             if (_srcTexture == null)
    40.                 _srcTexture = resolvedStyle.backgroundImage.texture ?? resolvedStyle.backgroundImage.sprite?.texture;
    41.  
    42.             if (_srcTexture == null)
    43.                 return;
    44.  
    45.  
    46.             style.backgroundImage = ToTexture2D();
    47.             this.MarkDirtyRepaint();
    48.         }
    49.  
    50.         private Texture2D ToTexture2D()
    51.         {
    52.  
    53.             RenderTexture currentRT = RenderTexture.active;
    54.  
    55.             var renderTexture = new RenderTexture(_srcTexture.width, _srcTexture.height, 32);
    56.             Graphics.Blit(_srcTexture, renderTexture, _blurMaterial);
    57.  
    58.             RenderTexture.active = renderTexture;
    59.             var texture2D = new Texture2D(_srcTexture.width, _srcTexture.height, TextureFormat.RGBA32, false);
    60.             texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
    61.             texture2D.Apply();
    62.  
    63.             RenderTexture.active = currentRT;
    64.  
    65.             return texture2D;
    66.         }
    67.  
    68.         public new class UxmlFactory : UxmlFactory<BlurImage, UxmlTraits> { }
    69.         public new class UxmlTraits : VisualElement.UxmlTraits
    70.         {
    71.             private readonly UxmlIntAttributeDescription _radius = new()
    72.             {
    73.                 name = "radius",
    74.                 defaultValue = 10
    75.             };
    76.  
    77.             public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
    78.             {
    79.                 base.Init(ve, bag, cc);
    80.                 var image = ve as BlurImage;
    81.  
    82.                 image.Radius = _radius.GetValueFromBag(bag, cc);
    83.             }
    84.         }
    85.     }
    86. }
    The shader:
    Code (CSharp):
    1. Shader "Custom/Blur"
    2. {
    3.     Properties
    4.     {
    5.         _Radius("Radius", Range(1, 255)) = 1
    6.     }
    7.  
    8.     Category
    9.     {
    10.         Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Opaque" }
    11.  
    12.         SubShader
    13.         {
    14.             GrabPass
    15.             {
    16.                 Tags{ "LightMode" = "Always" }
    17.             }
    18.  
    19.             Pass
    20.             {
    21.                 Tags{ "LightMode" = "Always" }
    22.  
    23.                 CGPROGRAM
    24.                 #pragma vertex vert
    25.                 #pragma fragment frag
    26.                 #pragma fragmentoption ARB_precision_hint_fastest
    27.                 #include "UnityCG.cginc"
    28.  
    29.                 struct appdata_t
    30.                 {
    31.                     float4 vertex : POSITION;
    32.                     float2 texcoord: TEXCOORD0;
    33.                 };
    34.  
    35.                 struct v2f
    36.                 {
    37.                     float4 vertex : POSITION;
    38.                     float4 uvgrab : TEXCOORD0;
    39.                 };
    40.  
    41.                 v2f vert(appdata_t v)
    42.                 {
    43.                     v2f o;
    44.                     o.vertex = UnityObjectToClipPos(v.vertex);
    45.                     #if UNITY_UV_STARTS_AT_TOP
    46.                     float scale = -1.0;
    47.                     #else
    48.                     float scale = 1.0;
    49.                     #endif
    50.                     o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
    51.                     o.uvgrab.zw = o.vertex.zw;
    52.                     return o;
    53.                 }
    54.  
    55.                 sampler2D _GrabTexture;
    56.                 float4 _GrabTexture_TexelSize;
    57.                 float _Radius;
    58.  
    59.                 half4 frag(v2f i) : COLOR
    60.                 {
    61.                     half4 sum = half4(0,0,0,0);
    62.  
    63.                     #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)))
    64.  
    65.                     sum += GRABXYPIXEL(0.0, 0.0);
    66.                     int measurments = 1;
    67.  
    68.                     for (float range = 0.1f; range <= _Radius; range += 0.1f)
    69.                     {
    70.                         sum += GRABXYPIXEL(range, range);
    71.                         sum += GRABXYPIXEL(range, -range);
    72.                         sum += GRABXYPIXEL(-range, range);
    73.                         sum += GRABXYPIXEL(-range, -range);
    74.                         measurments += 4;
    75.                     }
    76.  
    77.                     return sum / measurments;
    78.                 }
    79.                 ENDCG
    80.             }
    81.             GrabPass
    82.             {
    83.                 Tags{ "LightMode" = "Always" }
    84.             }
    85.  
    86.             Pass
    87.             {
    88.                 Tags{ "LightMode" = "Always" }
    89.  
    90.                 CGPROGRAM
    91.                 #pragma vertex vert
    92.                 #pragma fragment frag
    93.                 #pragma fragmentoption ARB_precision_hint_fastest
    94.                 #include "UnityCG.cginc"
    95.  
    96.                 struct appdata_t
    97.                 {
    98.                     float4 vertex : POSITION;
    99.                     float2 texcoord: TEXCOORD0;
    100.                 };
    101.  
    102.                 struct v2f
    103.                 {
    104.                     float4 vertex : POSITION;
    105.                     float4 uvgrab : TEXCOORD0;
    106.                 };
    107.  
    108.                 v2f vert(appdata_t v)
    109.                 {
    110.                     v2f o;
    111.                     o.vertex = UnityObjectToClipPos(v.vertex);
    112.                     #if UNITY_UV_STARTS_AT_TOP
    113.                     float scale = -1.0;
    114.                     #else
    115.                     float scale = 1.0;
    116.                     #endif
    117.                     o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
    118.                     o.uvgrab.zw = o.vertex.zw;
    119.                     return o;
    120.                 }
    121.  
    122.                 sampler2D _GrabTexture;
    123.                 float4 _GrabTexture_TexelSize;
    124.                 float _Radius;
    125.  
    126.                 half4 frag(v2f i) : COLOR
    127.                 {
    128.  
    129.                     half4 sum = half4(0,0,0,0);
    130.                     float radius = 1.41421356237 * _Radius;
    131.  
    132.                     #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)))
    133.  
    134.                     sum += GRABXYPIXEL(0.0, 0.0);
    135.                     int measurments = 1;
    136.  
    137.                     for (float range = 1.41421356237f; range <= radius * 1.41; range += 1.41421356237f)
    138.                     {
    139.                         sum += GRABXYPIXEL(range, 0);
    140.                         sum += GRABXYPIXEL(-range, 0);
    141.                         sum += GRABXYPIXEL(0, range);
    142.                         sum += GRABXYPIXEL(0, -range);
    143.                         measurments += 4;
    144.                     }
    145.  
    146.                     return sum / measurments;
    147.                 }
    148.                 ENDCG
    149.             }
    150.         }
    151.     }
    152. }
     
    Prodigga likes this.
  14. divvelaRavi

    divvelaRavi

    Joined:
    Jul 8, 2020
    Posts:
    9
    did you get any solution for this?
     
  15. Oneiros90

    Oneiros90

    Joined:
    Apr 29, 2014
    Posts:
    77
    Unfortunately, no
     
  16. unity_BA3036A5CF9EA7D4F796

    unity_BA3036A5CF9EA7D4F796

    Joined:
    Dec 16, 2022
    Posts:
    3
    Anything new in this realm? :)
     
  17. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,127
    Shameless self-plug*:

    I have made an asset for that. It supports Built-In, URP and HDRP and also takes care of all the borders, padding and round corners.

    If anyone who has posted in this thread before is interested in a free voucher, PM me. It's fairly new and I am always looking for feedback :)

    Links: Forum Thread, Asset Store, Manual

    * @Mods: If promoting the asset here is not okay please just delete my post. I stumbled upon this while googling and thought it might be a nice addition to the thread. Thank you.
     
    AlexandreT-unity likes this.
  18. joseGuate97

    joseGuate97

    Joined:
    Mar 1, 2018
    Posts:
    55
    Hi @mcoted3d, you said that it was on the roadmap? Is it supported now?

    It would be nice to have the ability to blur as easily as in CSS

    Code (CSharp):
    1. .blurry-div {
    2.   filter: blur(10px);
    3. }
    4.  
     
  19. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    970
    This is still on the roadmap, but not supported right now. We are currently reworking the render backend to support that.